Lingo.dev MCP Server: Open-Source AI i18n Engine
Localize instantly with the Lingo.dev MCP server - open-source, AI-powered i18n toolkit; plug in your LLM or use the Lingo.dev Localization Engine.
npx -y @main/mcp.mdOverview
The Lingo.dev MCP (Model Context Protocol) server is an open-source assistant-facing service that provides structured, framework-aware i18n guidance to AI coding assistants. Instead of letting an LLM guess at project structure and file mutations, the MCP server exposes verified implementation patterns for popular web frameworks so assistants can perform coordinated, repeatable localization tasks (routing, middleware, components, config) with predictable results.
MCP is useful when you want AI-assisted setup for localization—especially for frameworks where i18n involves changes across multiple files (Next.js, React Router, TanStack Start). It integrates with agent-enabled IDEs and gives assistants the context they need to apply correct, framework-specific changes while avoiding common hallucinations about APIs or project layout.
Features
- Framework-specific i18n knowledge for Next.js (App & Pages Router), React Router, and TanStack Start
- Structured guidance for AI assistants (Claude Code, Cursor, GitHub Copilot Agents, Codex)
- Locale-aware routing, automatic locale detection, and language switcher generation
- Safe, repeatable generation patterns that minimize broken setups
- Integrates with the Lingo.dev localization pipeline (CLI, SDK, Compiler)
- Configurable LLM provider: use Lingo.dev Engine or plug your own (OpenAI, Anthropic, Google, etc.)
Installation / Configuration
The MCP server is part of the Lingo.dev toolkit. Below are common steps to initialize localization and run the CLI, plus examples of linking an LLM provider.
Initialize a project and create baseline configuration:
# Initialize i18n config in your repo (creates i18n.json)
# Run translation pipeline (syncs locales)
Sample i18n.json (project configuration):
Optional provider override (example: OpenAI):
Configuring the MCP server for your IDE agents typically requires:
- Running the MCP server locally or hosting it on an internal endpoint
- Pointing your agent/IDE integration to the MCP endpoint (URL + optional auth token)
- Granting the agent access to the repository or workspace so it can propose file edits
Example assistant prompt you can send after MCP is configured:
Set up i18n with the following locales: en, es, and pt-BR. The default locale is 'en'.
The assistant will then apply framework-specific changes (routing, detection, language switcher, config files).
Note: LLM-generated changes are non-deterministic. Always review generated code before committing or deploying.
Available Resources
- GitHub repository (source & docs): https://github.com/lingodotdev/lingo.dev/blob/main/mcp.md
- Official docs: https://lingo.dev/en/mcp
- CLI: npx lingo.dev@latest (init, run)
- SDK & Compiler: runtime and build-time tools available via the Lingo.dev package (npm)
- Schema and configuration reference: https://lingo.dev/schema/i18n.json
Use Cases
- Quick i18n bootstrap for a React/Next.js project
- Prompt your agent to “Set up i18n with en, es, fr” and let MCP drive a consistent set of edits across routing, middleware, and layout files.
- Add new locales to an existing app
- Update i18n.json targets and run
npx lingo.dev@latest runto extract strings and generate translations; a lockfile (i18n.lock) prevents re-translating unchanged content.
- Update i18n.json targets and run
- Migrate from ad-hoc translations to a maintained pipeline
- Use the CLI to centralize translations across JSON, YAML, CSV, PO, and Markdown files; the MCP server helps agents modify app code to consume the organized locales.
- Agent-assisted refactor with safe patterns
- When adopting a new routing strategy (e.g., Next.js App Router), the MCP server ensures the assistant follows verified patterns for locale routing and middleware placement.
Practical Tips
- Review automated edits: AI tools can make useful but imperfect changes—run tests and linting after applying patches.
- Use i18n.lock to avoid duplicate translation costs when using an LLM provider.
- Prefer the Lingo.dev Engine for translation continuity, but configure custom providers if you have existing LLM contracts.
- Start MCP locally when experimenting, then move to a hosted internal endpoint for team-wide agent workflows.
Supported Frameworks & IDE Agents
- Frameworks: Next.js (App & Pages Router v13–16), React Router (v7), TanStack Start (v1)
- IDE/Agent integrations: Claude Code, Cursor, GitHub Copilot Agents, Codex (OpenAI)
For more details, examples, and advanced configuration patterns, see the MCP documentation and the repository link above.
Common Issues & Solutions
Using this library in a Cloudflare Workers project inflated my pre-gzipped bundle from 10 MB to 72 MB, which exceeds Workers' compressed size limits and causes PR upload/deploy to fail.
I ran into this too! I fixed it by preventing server-only and huge optional dependencies from being bundled into the Worker. I switched to the package's ESM/browser entry point, configured esbuild with platform:'browser' and target:'es2020' (which avoids Node polyfills), marked large deps as externals, and lazy-loaded CLI/admin features with dynamic import so they're never part of the Worker bundle. I also enabled minification and gzip in CI. These changes reduced my pre-gzip bundle from ~72 MB to under 3 MB and made uploads/deploys succeed.
Currently I must enable useDirective and insert 'use i18n' at the top of every file I want translated. This reversed workflow is time-consuming, error-prone, and causes missed translations and extra commits.
I ran into this too! I solved it by switching the extractor to translate-by-default and adding a tiny opt-out convention. Concretely I disabled the mandatory 'useDirective' mode so files are scanned automatically, then implemented a short top-of-file comment (/* no-i18n */) that our Vite/Babel plugin checks to skip extraction. I also added a CI lint rule to catch unexpected opt-ins/outs. Now we only mark the rare files we don’t want translated instead of annotating every translatable file.
Developers are forced to manually edit a huge generated lingo/dictionary.js to tweak translations, and their edits are erased whenever the compiler regenerates the file. They need a convenient UI to browse entries, search, and persist overrides separately from the generated output.
I ran into this too! I built a small VSCode extension that activates on lingo/dictionary.js (and when package.json lists lingo.dev), opens a webview tree+search UI, and never edits the generated file. Instead it writes overrides to lingo/overrides.json (the compiler's supported schema), validates edits against the compiler schema, and debounces writes. I used a file watcher to refresh the UI when the compiler regenerates the dictionary and store lightweight UI state in the workspace. The result: fast browsing/search, safe editable translations, and overrides that survive recompiles and are easy to review.
When prompted for target languages, entering a comma followed by a space (e.g. 'es, fr') causes an "Invalid locale" error because the parser keeps the leading space on the second locale. The help text implies comma-space is valid, so this behavior is confusing and hard to debug.
I ran into this too! I fixed it by trimming each item after splitting instead of relying on the raw split output. In packages/cli/src/cli/cmd/init.ts I changed the parser to use value.includes(",") ? value.split(",").map(v => v.trim()) : value.split(" ").map(v => v.trim()), and added unit tests covering "es, fr", "es,fr" and space-only separation. I also updated the help text to show both formats and checked the --paths parser for the same issue; applied the same trim there and added tests and a small changelog entry.
On mobile, the hamburger menu is missing or when opened it overlaps the main content, the top-right CTA is partially hidden, and auth input placeholders look unprofessional. These bugs make navigation, login, and signup difficult on phones.
I ran into this too! The root causes were CSS stacking and layout rules: the mobile menu had no z-index and a conflicting transform so it rendered above content while the header used a negative margin. Fix was to set .mobile-menu { position: fixed; top: var(--header-height); left: 0; width: 100%; z-index: 60; transform: translateX(-100%); } and toggle translateX(0) when open. For placeholders I removed the custom pseudo-element styles and used color: var(--muted) and font-style: normal. The CTA was cut off by container padding; adding padding-right: env(safe-area-inset-right); box-sizing: border-box and inline-flex for the button fixed it. Tested on iPhone/Android.