paraglide-mcp

paraglide-mcp

Enables translation of i18n messages in Paraglide JS projects by serving small batches, validating translations against source structure, and saving them per locale through inlang's SDK.

Category
访问服务器

README

paraglide-mcp

An MCP (Model Context Protocol) server for translating Paraglide JS / inlang projects.

The agent calling the tools is the translator. The server's job is to make that safe and efficient: it serves messages in small batches, validates every translation against the source (placeholders, markup, variant structure) before anything is written, and reports progress so the agent knows exactly when a locale is done. Faulty items are rejected individually — one bad translation never blocks or corrupts the rest of the batch.

Quick start

No installation needed — run it via npx from your MCP client configuration. Add this to your project's .mcp.json (Claude Code) or claude_desktop_config.json:

{
  "mcpServers": {
    "paraglide": {
      "command": "npx",
      "args": ["-y", "paraglide-mcp", "--project", "./project.inlang"]
    }
  }
}

--project is optional: by default the server looks for project.inlang in the working directory, then for a single *.inlang directory up to one level deep.

The server is stateless — it loads your inlang project from disk per tool call and writes changes straight back through your project's own inlang plugin (e.g. @inlang/plugin-message-format), so messages/{locale}.json files always stay in the exact format the rest of your toolchain expects. External edits (your editor, the Paraglide compiler, git) are always picked up. If the configured plugin can't be fetched (offline, no cache), a bundled copy of the message-format plugin is used as a fallback.

Works with the standard Paraglide JS setup out of the box, and with i18next, next-intl, and ICU MessageFormat projects through their inlang plugins — see COMPATIBILITY.md for the full support matrix (and why PO/XLIFF are not supported).

Tools

Tool Purpose
project_info Locales, base locale, and per-locale translated/missing counts.
list_message_keys Keys only (cheap), filterable by key prefix (startsWith) and per-locale status (missing / translated), with cursor pagination.
get_messages Full message content by exact keys or prefix, optionally restricted to specific locales.
search_messages Find messages by text content or key substring (case-insensitive) — for when you know the UI text ("Add to cart") but not the key.
get_translation_batch The next N untranslated messages for a target locale (default 5, max 25), with source text, required placeholders, and a remaining counter.
save_translations Validate and persist translations for one locale (max 25 per call). Per-item results; valid items are saved even when others fail.
delete_messages Delete messages by key from every locale (max 25 per call). Unknown keys are rejected individually while the rest are still deleted.
rename_message Rename a message key across every locale, keeping all translated values. Fails without changes when the old key is missing or the new key is taken.
add_locale Add a locale to the project settings (and seed an empty message file for message-format projects). Locale tags are stored as-is — no format opinion.
remove_locale Remove a locale from the settings and delete its message file. Reports how many translations were discarded; the base locale can't be removed.

Prompts

The server also exposes the common workflows as MCP prompts, so clients that support prompts (e.g. /mcp__paraglide__translate_locale in Claude Code) can launch them directly without the bundled skill:

Prompt Arguments Purpose
translate_locale targetLocale, sourceLocale? Translate all missing messages into one locale via the batch loop.
translate_prefix prefix, targetLocale, sourceLocale? Same loop, scoped to keys starting with prefix.
review_locale locale, prefix? Review existing translations against the base locale and fix problems.

Locale and prefix arguments support MCP completion: locales are suggested from the project settings, prefixes from the actual message keys.

Resources

Read-only project state is also exposed as MCP resources, so clients can pin it as context (e.g. @-mention in Claude Code) without spending tool calls:

Resource Purpose
paraglide://project/info Project overview — same payload as the project_info tool.
paraglide://locales/{locale}/missing All keys missing or empty in {locale}. One resource per project locale appears in the resource list.
paraglide://messages/{locale}/{key} The value of one message in one locale (value is null when untranslated).

All resources return JSON. The {locale} and {key} template variables support MCP completion, like the prompt arguments.

The translation loop

Agents translate iteratively — small batches keep the error rate low while the loop keeps throughput high (no re-reading of the full catalog between steps, and remaining tells the agent exactly when to stop):

project_info
└─ for each target locale:
   ┌─> get_translation_batch { targetLocale: "de", batchSize: 5 }
   │   ... agent translates the 5 items ...
   │   save_translations { targetLocale: "de", translations: [...] }
   └── repeat until done == true

Scope work to a subsection of the catalog with prefix, e.g. only checkout_* messages:

{ "targetLocale": "de", "prefix": "checkout_", "batchSize": 5 }

Message values

Values use the inlang message format — exactly what's in your messages/{locale}.json files:

// simple message
"Hello {name}!"

// multi-variant message (plurals, gender, ...)
[{
  "declarations": ["input count", "local countPlural = count: plural"],
  "selectors": ["countPlural"],
  "match": {
    "countPlural=one": "You have {count} message",
    "countPlural=other": "You have {count} messages"
  }
}]

Translations may change shape when the target language requires it (e.g. a string becomes a plural variant set for Czech) as long as introduced selectors are declared.

Variant arrays with more than one element (found in some legacy or hand-written files) are read in full — placeholders from every element count — but can't be saved back as-is, because the message-format plugin and the Paraglide compiler silently ignore everything after the first element. The save error explains the fix: consolidate all variants into one element's match.

Validation

save_translations rejects, per item:

  • placeholders that don't exist in the source message (typo guard — a {nmae} would otherwise silently become a new input variable),
  • markup tags ({#bold}…) not present in the source,
  • match conditions using undeclared selectors,
  • structurally invalid values,
  • unknown message keys (unless allowNewKeys: true is passed deliberately).

Dropped source placeholders produce warnings, not errors, since languages legitimately drop variables in some variants.

The source-comparison checks can be bypassed per call with skipValidation: true — for translations that deliberately diverge from the source, e.g. when the target doesn't need a placeholder. Structural validation and the unknown-key guard still apply.

Agent skill

skill/paraglide-translation/ contains an installable skill that teaches an agent the batch workflow, plural-rule handling, and error recovery. It uses the open Agent Skills format, so it works with any agent that supports SKILL.md (Claude Code, Codex, Cursor, Copilot, Gemini CLI, ...).

Claude Code — install the plugin, which bundles both the MCP server and the skill (no .mcp.json needed):

/plugin marketplace add WesHaze/paraglide-mcp
/plugin install paraglide-translation@paraglide-mcp

Any other agent — install the skill with the skills CLI (it picks the right directory for your agent), then configure the MCP server as shown in Quick start:

npx skills add WesHaze/paraglide-mcp

Or copy it manually:

cp -r node_modules/paraglide-mcp/skill/paraglide-translation .claude/skills/
# or globally: cp -r ... ~/.claude/skills/

Development

pnpm install
pnpm test        # unit + integration tests (no build needed)
pnpm test:e2e    # builds, then drives the real CLI over stdio MCP
pnpm test:all    # everything
pnpm bench       # performance benchmark (see PERFORMANCE.md)
pnpm build

Integration and e2e tests run against a real inlang project fixture on disk using the actual @inlang/sdk — no mocks.

Message-format projects are read and written directly as JSON instead of through the SDK's load/save cycle — see PERFORMANCE.md for the measurements and rationale.

Releasing

Releases are automated: pushing a v* tag runs release.yml, which tests, publishes to npm via trusted publishing (OIDC — no token secrets), and syncs the version to the official MCP Registry.

One-time setup before the first tagged release:

  1. Publish the first version locally (pnpm build && npm publish) — npm only lets you configure a trusted publisher for a package that already exists.
  2. On npmjs.com → package → Settings, add a GitHub Actions trusted publisher: org WesHaze, repository paraglide-mcp, workflow filename release.yml.
  3. Set publishing access to "Require two-factor authentication and disallow tokens".

Then release with:

npm version patch   # bumps package.json, commits, tags
git push --follow-tags

Requirements

  • Node.js >= 20
  • An inlang project (Paraglide JS default setup works out of the box) — see COMPATIBILITY.md for supported formats and plugins

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选