Skip to main content
Glama
Murzav

paraglide-i18n-mcp

by Murzav

paraglide-i18n-mcp

MCP server for Paraglide JS / inlang i18n catalogs. Lets an MCP-aware client (Claude Code, Codex, etc.) manage translations, variants, and plural forms without parsing catalog files itself.

This is a pre-release scaffold at v0.1.0. The package is not on npm yet; install from source. Sister project of xcstrings-mcp, which does the same job for Apple .xcstrings.

What it does

Exposes 24 tools and 4 MCP resources over stdio. The client calls them, the server does the catalog I/O.

The interesting part is what it refuses to do. Translation work belongs to the LLM. The server does not generate text. It validates placeholders, plural completeness against CLDR, markup balance, schema integrity. Writes go through an atomic protocol: temp file, fsync, rename, fsync parent, per-file mutex. Path traversal, OOM via oversized inputs, and ReDoS regexes all get rejected at the boundary, not at the handler.

Tools group by area:

Area

Tools

Project lifecycle

discover_files, parse_paraglide, list_files, health_check

Translation

get_untranslated, get_coverage, validate_translations, submit_translations

Keys

add_keys, delete_keys, rename_key, search_keys, get_key, get_context

Variants, plurals

get_variants, add_variant, add_variant_arm, get_plurals, submit_plural_forms

Locale

list_locales, add_locale, remove_locale

Diff, build

get_diff, compile_messages

Every tool description carries a structured shape (Use after, Errors, Capabilities, Response, Limits, Pair with) so the LLM knows when to call it and what to expect back without round-tripping through the input schema.

Install (local, pre-npm)

Clone and build:

git clone https://github.com/Murzav/paraglide-i18n-mcp.git
cd paraglide-i18n-mcp
bun install --frozen-lockfile
bun run build

This produces dist/bin/cli.mjs (ESM). Runs on Node ≥22.17 or Bun ≥1.3.

If you don't have bun installed, get it from bun.sh (one-line installer) or use npm equivalents at your own risk (the lockfile is bun.lock, so install order may differ).

Wire it into your MCP client

Claude Code

Add to your MCP settings (the file path varies by platform; check Claude Code docs):

{
  "mcpServers": {
    "paraglide": {
      "command": "node",
      "args": ["/abs/path/to/paraglide-i18n-mcp/dist/bin/cli.mjs"]
    }
  }
}

Codex CLI

# ~/.codex/config.toml
[[mcp_servers]]
name = "paraglide"
command = "node"
args = ["/abs/path/to/paraglide-i18n-mcp/dist/bin/cli.mjs"]

Any MCP client

The server speaks JSON-RPC over stdio. Spawn node dist/bin/cli.mjs and hold stdin/stdout open. The CLI takes no runtime flags; configure it via the env vars below.

To verify the binary works at all:

node dist/bin/cli.mjs --version
node dist/bin/cli.mjs --help

Configuration

Environment variables:

Var

Default

What it does

PARAGLIDE_MCP_LOG_LEVEL

info

trace / debug / info / warn / error / silent. All logs go to stderr (stdout is reserved for JSON-RPC).

PARAGLIDE_MCP_LOG_FORMAT

pretty

pretty for terminals, json for log aggregators.

PARAGLIDE_MCP_WORKSPACE_ROOT

$PWD

discover_files refuses any root outside this directory. Defaults to the server's cwd.

PARAGLIDE_MCP_INCLUDE_STACK

unset

Set to 1 to include stack frames in JSON-RPC error payloads. Off by default so absolute paths don't leak to clients.

PARAGLIDE_MCP_IDLE_TTL_MS

300000

After this many ms idle, a cached project is evicted (handle closed, ~200 MB RSS released). Next access re-parses from disk. Set to 0 to disable the idle sweeper.

Quick workflow

A typical session looks like:

  1. discover_files to find inlang projects under a directory, or skip straight to step 2 if you already know the path.

  2. parse_paraglide to load and cache it.

  3. get_untranslated (or get_coverage) to see what's missing.

  4. submit_translations for flat bundles, or add_variant_arm / submit_plural_forms for variant bundles, to write.

  5. validate_translations to catch placeholder, plural, or markup issues before they reach production.

  6. compile_messages to run paraglide-js codegen.

get_diff between snapshots tells you what changed since the last parse_paraglide. health_check reports server version, installed @inlang/sdk version, and cached projects. Use it as a smoke test when wiring the server into a new client.

Status & quality

  • 3 ultrareview rounds across the codebase. 50 unique findings, 49 fixed, 1 deferred with documented rationale.

  • 610 tests across 92 files. Coverage: statements 97%, branches 90%, functions 99%, lines 97%.

  • v0.1.0 supports plugin-message-format v4 only. Other plugins resolve to a read-only stub. Full multi-plugin write support lands in v0.1.x.

  • @inlang/sdk pinned to exact 2.9.3. health_check warns on an installed-version mismatch.

See docs/spec.md for design decisions, CHANGELOG.md for release notes.

Development

bun run test          # vitest one-shot
bun run test:watch    # vitest watch
bun run coverage      # v8 coverage report
bun run lint          # oxlint
bun run format:check  # oxfmt
bun run typecheck     # tsc --noEmit
bun run dev           # run the server with --watch

The pre-commit hook runs lint + format + typecheck on staged files. Don't bypass it.

License

Dual-licensed under either of:

at your option.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Murzav/paraglide-i18n-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server