blocks-translation-mcp
This MCP server automates UI translation key management for the Blocks/UILM portal — scanning codebases for new/changed keys, deduplicating against a tenant, and generating import-ready JSON.
Scan & extract translation keys from your git diff (working tree, staged, untracked) using built-in extractors for
ngx-translate,react-i18next, or a generic regex mode.One-call prep with
prepare_sync: scans the diff, groups keys by Blocks module, fetches tenant cultures, and performs exact deduplication, returning a ready-to-use structure.Deduplication:
search_keyschecks for exact KeyName matches and duplicate English text across target and shared modules to prevent redundant uploads.Tenant introspection:
list_culturesretrieves supported translation cultures (cached, refreshable);list_moduleslists available Blocks modules with IDs.Build upload JSON:
build_upload_entriesassembles already-translated keys into the exact JSON format the Blocks portal expects (including UUID, TenantId, ModuleId, etc.).End-to-end sync:
sync_keyscombines dedup-checking, JSON building, and writing per-module upload files to disk, reporting skipped existing keys and duplicate-text warnings.Configuration: Driven by a per-project
.env.blocks-translationfile — no hardcoded secrets, framework-agnostic, supports any language set.Client compatibility: Works with Claude Code, Cursor, Codex, Windsurf, VS Code, Zed, and any stdio MCP client.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@blocks-translation-mcpsync the translation keys"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Blocks Translation MCP
An MCP server that finds new UI translation keys in your codebase, dedup-checks them against a Blocks/UILM tenant, and generates the JSON the Blocks portal expects for import — for any project, framework, or language set, driven by a single per-project config file.
It never guesses tenant IDs, module names, or supported languages — those are resolved live from your config and the tenant itself. Translation text is inferred/authored by the agent; this server does the deterministic parts (diff scanning, dedupe, exact JSON stamping) in code so they're fast, cheap, and reliable.
Works in any MCP client — Claude Code, Cursor, Codex, Google Antigravity, Pi, Windsurf, Cline, VS Code, Zed, …
Any frontend framework — built-in
ngx-translateandreact-i18nextextractors, plus agenericregex mode for anything else.Zero hardcoded languages — cultures come from the tenant's own
Language/GetsAPI and are cached per project.Per-project config — one
.env.blocks-translationfile at each consuming repo's root; no secrets ever live in this server.
Contents
Add to your AI tool — Claude Code · Cursor · Codex · Antigravity · Pi · Windsurf · Cline · VS Code · Zed · generic
Related MCP server: Localizable XStrings MCP Server
Quick start
# 1. Build the server (once)
git clone <repo-url> blocks-translation-mcp
cd blocks-translation-mcp && npm install && npm run build
# 2. Configure a project that uses Blocks
cp .env.blocks-translation.example /path/to/your/project/.env.blocks-translation
# …then fill in BLOCKS_TENANT_ID, BLOCKS_PORTAL_KEY, BLOCKS_USERNAME, BLOCKS_PASSWORD
# 3. Register the server in your AI tool (see "Add to your AI tool"), then just ask:
# "sync the translation keys"Tools
Tool | What it does |
| The one prep call. Scans the project diff (working-tree + staged + untracked), groups keys by their own module, fetches the tenant cultures, and exact-dedupes — all in code. Returns |
| Dedup-check + build + write the upload JSON in one call (one file per module). Reports |
| Standalone: extract translation keys from the git diff for the configured framework ( |
| The tenant's supported cultures (from the Blocks Language API, cached). |
| Modules in the tenant (name + id). |
| Dedup-check keys against a module (+ any |
| Pure JSON assembly of already-translated keys into the portal's import shape. |
Most of the time the agent only needs prepare_sync → sync_keys; the rest are composable building blocks.
Install
Recommended: one command (auto-detects your AI tools)
npx -y github:mahmudul006/blocks-translation-mcp installThis detects the AI tools installed on your machine (Claude Code, Cursor, Codex, Antigravity, Pi, Windsurf, Cline, VS Code, Zed…), asks global vs project, and registers the server into each — using each tool's own CLI or config format. It backs up any file before editing and only ever touches its own blocks-translation entry.
Flags (all optional — omit them to be prompted):
Flag | Effect |
| Dry run: show every planned change, write nothing. |
| Skip the scope prompt. |
| Project root for a project install (default: current dir). |
| Skip the client picker. |
| Accept all defaults (non-interactive). |
Requires Node ≥ 18; no clone or build. Then configure your project (the .env.blocks-translation) and restart your tool.
Uninstall / re-try
npx -y github:mahmudul006/blocks-translation-mcp uninstall # prompts for scope
npx -y github:mahmudul006/blocks-translation-mcp uninstall --scope global --yesRemoves only the blocks-translation entry from each tool (via its remove-CLI or by editing its config, backing up first), and lists any you must remove by hand. Accepts the same --scope / --root / --print flags.
Re-fetching a new version:
npx github:caches the cloned repo, so after the server is updated on GitHub, clear the cache before re-running:rm -rf ~/.npm/_npx.
Manual / from source
If you'd rather not use npx github:, clone and build, then use the per-client blocks below with node /abs/path/to/dist/index.js instead of the npx command:
git clone https://github.com/mahmudul006/blocks-translation-mcp
cd blocks-translation-mcp && npm install && npm run buildAdd to your AI tool
The installer above does this for you. To do it by hand, every client runs the same stdio command:
npx -y github:mahmudul006/blocks-translation-mcpOnly two things differ per client: where the config lives and its wrapper key (mcpServers JSON, VS Code's servers, Zed's context_servers, or Codex's TOML). If your client doesn't start the server with its working directory set to your project root, add "BLOCKS_PROJECT_ROOT": "/abs/path/to/your/project" to the server's env (see How the server finds your project).
GUI clients + nvm: the one-command installer handles this, but if you configure a GUI client (Antigravity, Cursor, Windsurf, VS Code) by hand and Node is installed via nvm, use an absolute
command(full path tonpx) and add your Node bin dir toenv.PATH— otherwise the tool can't findnpx/node. See Troubleshooting. Command-line clients (Claude Code, Codex) don't need it.
Claude Code
claude mcp add blocks-translation -- npx -y github:mahmudul006/blocks-translation-mcpor in .mcp.json (project) / ~/.claude.json (global):
{ "mcpServers": { "blocks-translation": {
"command": "npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"]
} } }Claude Code sets the server's cwd to your project root, so .env.blocks-translation is found automatically — no BLOCKS_PROJECT_ROOT needed.
Cursor
.cursor/mcp.json (project) or ~/.cursor/mcp.json (global):
{ "mcpServers": { "blocks-translation": {
"command": "npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"],
"env": { "BLOCKS_PROJECT_ROOT": "/abs/path/to/your/project" }
} } }Codex (OpenAI Codex CLI)
~/.codex/config.toml (or a project .codex/config.toml):
[mcp_servers.blocks-translation]
command = "npx"
args = ["-y", "github:mahmudul006/blocks-translation-mcp"]
[mcp_servers.blocks-translation.env]
BLOCKS_PROJECT_ROOT = "/abs/path/to/your/project"or via CLI:
codex mcp add blocks-translation --env BLOCKS_PROJECT_ROOT=/abs/path/to/your/project -- npx -y github:mahmudul006/blocks-translation-mcpGoogle Antigravity
In the IDE: Manage MCP Servers → View raw config, or edit .agents/mcp_config.json (workspace) / ~/.gemini/config/mcp_config.json (global):
{ "mcpServers": { "blocks-translation": {
"command": "npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"],
"env": { "BLOCKS_PROJECT_ROOT": "/abs/path/to/your/project" }
} } }Pi (pi coding agent)
.mcp.json in your project (or the pi agent directory). Pi supports a cwd field, so you can point the server at your repo directly:
{ "mcpServers": { "blocks-translation": {
"command": "npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"],
"cwd": "/abs/path/to/your/project"
} } }Because Pi loads .mcp.json from the project cwd, a project-local config also finds .env.blocks-translation automatically.
Windsurf
~/.codeium/windsurf/mcp_config.json:
{ "mcpServers": { "blocks-translation": {
"command": "npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"],
"env": { "BLOCKS_PROJECT_ROOT": "/abs/path/to/your/project" }
} } }Cline (VS Code extension)
Cline → MCP Servers → Configure (cline_mcp_settings.json):
{ "mcpServers": { "blocks-translation": {
"command": "npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"],
"env": { "BLOCKS_PROJECT_ROOT": "/abs/path/to/your/project" }
} } }VS Code (Copilot agent mode)
.vscode/mcp.json — note VS Code uses servers (not mcpServers) and an explicit type:
{ "servers": { "blocks-translation": {
"type": "stdio",
"command": "npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"],
"env": { "BLOCKS_PROJECT_ROOT": "${workspaceFolder}" }
} } }Zed
settings.json — Zed uses context_servers:
{ "context_servers": { "blocks-translation": {
"source": "custom",
"command": "npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"],
"env": { "BLOCKS_PROJECT_ROOT": "/abs/path/to/your/project" }
} } }Any other MCP client (generic stdio)
Any client that speaks MCP over stdio works. Register a stdio server with:
command:
npxargs:
["-y", "github:mahmudul006/blocks-translation-mcp"]env (optional):
BLOCKS_PROJECT_ROOT(if the client doesn't setcwdto your repo), or the fullBLOCKS_*set instead of a.envfile.
Configure your project
Copy the example into your project's repo root (not this server's directory) and fill it in:
cp /abs/path/to/blocks-translation-mcp/.env.blocks-translation.example \
/abs/path/to/your/project/.env.blocks-translationAdd .env.blocks-translation (and .blocks-translation-cache.json) to your project's .gitignore — the config holds credentials.
Config is read lazily, only when a tool runs, with this precedence per key: explicit BLOCKS_* env vars (e.g. from your client's env block) win over values in .env.blocks-translation.
Variable | Required? | Default | Meaning |
| Yes | — | Your tenant GUID. Required for every tool. |
| For login / modules / languages | — | Portal app key used to authenticate the admin surface. |
| For login / modules / languages | — | Admin username for the login-required endpoints. |
| For login / modules / languages | — | Admin password. If it contains |
| No |
| Blocks API base URL. |
| No |
| Origin/Referer the admin surface requires. Override only for a non-cloud Blocks deployment. |
| No |
| Key extraction: |
| Only if | — | Regex whose first capture group is the key. |
| No |
| Output path template; |
| No | (empty) | Comma-separated shared modules to also dedup-check alongside the target (e.g. |
| Only if your client doesn't set | current working directory | Points the server at your project's root. |
How it works
The lean, token-cheap flow for adding or syncing translation keys — usually two tool calls:
prepare_sync— one call. Scans the diff (working-tree + staged + untracked), groups keys by their own module, fetches the tenant's cultures, and exact-dedupes each module's keys. Returns{ cultures, modules: [{ module, newKeys, existingSkip }] }.Translate — for each module's
newKeysonly, the agent infers English from the key name and translates into the returned cultures. (This server does not translate for you, and does not read your local i18n files — the portal is the source of truth.)sync_keys— once per module, writesblocks-translation-helper/blocks-upload.<module>.generated.json(path configurable) and reports anyduplicateWarnings(same English under a different existing key) for you to decide on.Manual portal import — importing the generated JSON into the Blocks portal is a step you do yourself; this server never calls a write/import endpoint.
In clients that surface MCP server instructions (e.g. Claude Code), this workflow is injected automatically. In clients that don't, just ask for a tool by name (e.g. "run prepare_sync").
Languages: on first use the server logs in, calls Language/Gets for your tenant, and caches the result to .blocks-translation-cache.json at your project root (with a module-name → id cache). Pass refresh:true to prepare_sync/list_cultures if the tenant later adds a language.
How the server finds your project
The server needs your project's root to read .env.blocks-translation, run git diff, and place the cache. It resolves it with this precedence:
Explicit
BLOCKS_*env vars set in your client's server config (highest priority).BLOCKS_PROJECT_ROOT/.env.blocks-translationifBLOCKS_PROJECT_ROOTis set.<cwd>/.env.blocks-translation— the zero-config default when the client setscwdto your project (Claude Code, project-local Pi).
So: on Claude Code (and project-local Pi) it just works; on other clients, set BLOCKS_PROJECT_ROOT (or put the BLOCKS_* vars straight in the env block).
Troubleshooting
"No Blocks config found for this project" — BLOCKS_TENANT_ID isn't set. Create .env.blocks-translation at your project root (copy the example) or set BLOCKS_PROJECT_ROOT / the BLOCKS_* vars in your client's env block.
Missing admin credentials (BLOCKS_USERNAME/BLOCKS_PASSWORD/BLOCKS_PORTAL_KEY not set) — prepare_sync, list_modules, and language lookups use the admin surface. Set all three.
406 Invalid_Origin_Or_Referer — your Blocks deployment isn't the default cloud host. Set BLOCKS_ORIGIN to your portal's origin.
exec: "npx": executable file not found in $PATH / /usr/bin/env: 'node': No such file or directory — a GUI-launched client (Antigravity, Cursor, Windsurf, VS Code) spawned the server without your shell's PATH, so node/npx aren't found. Common when Node is installed via nvm (its bin dir is only on PATH inside a shell that sourced nvm). The one-command installer fixes this automatically. If you configured the client by hand, you need both an absolute command (the host resolves it against its own stripped PATH, before env) and an env.PATH (for npx's node shebang and child node/git). Find your Node bin dir with dirname $(readlink -f $(which npx)):
"blocks-translation": {
"command": "/home/you/.nvm/versions/node/vX.Y.Z/bin/npx",
"args": ["-y", "github:mahmudul006/blocks-translation-mcp"],
"env": { "PATH": "/home/you/.nvm/versions/node/vX.Y.Z/bin:/usr/local/bin:/usr/bin:/bin" }
}CLI-installed clients (Claude Code, Codex) don't need this — they inherit your shell PATH.
find_keys/prepare_sync git error — they run git in the project root. Ensure the project is a git repo and git is on PATH; if your client doesn't set cwd, set BLOCKS_PROJECT_ROOT.
Admin vs. public surface — the admin surface (prepare_sync language/module lookups, list_modules, list_cultures) requires the login vars. The public surface (search_keys, the dedupe fetches) needs only BLOCKS_TENANT_ID.
Cultures look stale (a newly-added tenant language is missing) — call prepare_sync/list_cultures with refresh:true, or delete .blocks-translation-cache.json.
Available Tools
7 toolsbuild_upload_entriesBuild Blocks portal upload JSONA
Pure JSON assembly (aside from resolving moduleName -> id, which is cached to disk so it rarely needs a live call). Takes already-translated keys (translate them yourself first, matching tone across all 7 cultures) and stamps them into the exact array shape the Blocks portal JSON import expects: _id (new uuid), TenantId, ModuleId, Value: null, Routes: [], and IsPartiallyTranslated computed from whether all target cultures were provided. Run search_keys first to avoid re-uploading keys that already exist. Prefer sync_keys for the common case (dedup-check + build + write to disk in one call).
| Name | Required | Description | Default |
|---|---|---|---|
| entries | Yes | ||
| moduleId | No | Raw ModuleId, if already known. Takes priority over moduleName. | |
| tenantId | No | Defaults to BLOCKS_TENANT_ID from .env if omitted. | |
| moduleName | No | e.g. "app-survey" — resolved to a ModuleId via cache/list_modules. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses key behaviors: no translation performed ('translate them yourself first'), moduleName resolution cached to disk, and the computed IsPartiallyTranslated based on culture completeness. It stops short of explicitly saying it does not perform the actual import, but 'Pure JSON assembly' strongly implies it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences; each adds value. Front-loaded with the primary purpose and followed by necessary caveats and alternatives. Slightly long but every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description explains the output array shape, the caching behavior, the translation prerequisite, and tool alternatives. It gives enough context to use the tool correctly in a workflow. Could add error cases, but overall quite complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema documents 3 of 4 params (moduleId, tenantId, moduleName) with descriptions, but the required entries param has no schema description. Description compensates by explaining the expected entry content (already-translated keys, 7 cultures) and the exact output fields, adding meaningful context beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear and specific: 'Pure JSON assembly' plus the exact output shape ('stamps them into the exact array shape the Blocks portal JSON import expects'). Distinguishes itself from siblings by naming sync_keys and search_keys as alternatives for different cases.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance: 'Prefer sync_keys for the common case' and 'Run search_keys first to avoid re-uploading keys that already exist.' This clearly states when to use this tool vs the alternatives, covering both prerequisites and exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_keysFind new/changed translation keys in the current projectA
Scans the current project for added/changed translation keys and returns them deduped with their source-derived prefix, using the configured framework (ngx-translate | react-i18next | generic). In the default mode it reads the working-tree + staged diff AND brand-new untracked files (a common place for new keys); pass diffBase to compare against a ref instead. Does NOT resolve the Blocks module slug — use list_modules for that. Standalone building block; for a full sync prefer prepare_sync, which composes this with module/culture resolution and dedupe.
| Name | Required | Description | Default |
|---|---|---|---|
| diffBase | No | A git ref (e.g. "main") to diff against. Omit to use uncommitted changes (working tree + staged). | |
| framework | No | Override the configured BLOCKS_FRAMEWORK for this call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does a good job: it discloses default diff behavior, support for untracked files, deduplication, framework configurability, and a notable limitation (no module slug resolution). It doesn't explicitly state read-only semantics or return structure, but the scan nature implies safety.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: purpose, mode details, and exclusions/alternatives. Front-loaded with the main action and highly scannable, with no fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description provides reasonable return info (deduped with prefix) but lacks a precise return shape. It thoroughly covers inputs, modes, framework, and relationships to sibling tools, making it adequately complete for an agent to decide and invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters have detailed descriptions (diffBase explains git ref and default; framework explains override). The description adds marginal value by mentioning the default mode and framework list, but largely mirrors the schema, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool scans for added/changed translation keys and returns them deduped with a source-derived prefix. It explicitly differentiates from siblings by noting it does NOT resolve the Blocks module slug (list_modules) and is a standalone block (prepare_sync composes it).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance: default mode reads working-tree + staged diff plus untracked files, with an alternative diffBase mode. It also names alternatives—list_modules for slug resolution and prepare_sync for full sync—making the tool's role in the workflow crystal clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_culturesList the tenant's translation culturesA
Returns the culture codes this Blocks tenant supports (e.g. en-US, de-DE, ...), fetched from the Blocks Language API and cached to disk. Call this to learn exactly which cultures to translate into before sync_keys / build_upload_entries. Do NOT read local i18n files or rely on memory for the culture set — this tool is the source of truth. Also reports which culture is the tenant default. Pass refresh:true to re-fetch from the API if the tenant recently added a language.
| Name | Required | Description | Default |
|---|---|---|---|
| refresh | No | Re-fetch languages from the API, bypassing the cache. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the API source, disk caching, reports the default culture, and the refresh behavior. This is strong transparency, though it doesn't detail failure modes or side effects beyond caching.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: core purpose first, then usage guidance, a warning, and refresh semantics—all in four sentences with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one optional parameter and no output schema, the description covers purpose, usage, source of truth, and return content (culture codes + default). It is complete for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully documents the single 'refresh' parameter. The description adds practical semantics by explaining when to use refresh (if the tenant recently added a language), going beyond the schema's basic type/description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: it returns the culture codes supported by the tenant, with examples. It also distinguishes itself from siblings by declaring itself the source of truth and instructing not to read local i18n files.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is provided: call this before sync_keys/build_upload_entries, and do NOT rely on local files or memory. It also explains when to use the refresh parameter, making usage unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_modulesList Blocks modulesA
Lists modules available in the configured Blocks tenant (name + id). Use this to resolve a module name (e.g. "app-user-management", "root", "generic-app") to the ModuleId needed by search_keys and build_upload_entries.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions the output format and tenant context, but does not explicitly state that this is a read-only operation, any authorization requirements, rate limits, or side effects. For a simple listing tool, this coverage is insufficient without annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no unnecessary words. It front-loads the action and immediately adds practical usage context. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (0 params, no output schema), the description is complete: it states what is returned, examples of module names, and how the output is used by other tools. No additional context is needed for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4 per the rubric. The description adds value by clarifying the output structure (name + id) and usage, even though no parameter explanation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description uses a specific verb 'Lists' and clearly identifies the resource ('modules available in the configured Blocks tenant'), specifying the output as name + id. It also distinguishes itself from siblings by noting the purpose of resolving module names to ModuleIds needed by other tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use this to resolve a module name...to the ModuleId needed by search_keys and build_upload_entries.' This provides a clear use case and references specific downstream sibling tools, offering practical guidance beyond generic context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_syncOne-call prep: diff -> keys -> per-module cultures + exact dedupeA
The FIRST and usually ONLY prep call for a translation sync. Scans the project diff (working-tree + staged + untracked), groups the found keys BY THEIR OWN module (from each key's prefix), fetches the tenant cultures, and exact-dedupes each module's keys against that module + any modules in BLOCKS_DEDUP_MODULES (none by default) — all in code, no LLM work. Handles a diff spanning several modules in ONE call. Returns { cultures, modules: [{ module, newKeys, existingSkip }] }. Do NOT call find_keys / list_modules / list_cultures / search_keys separately — this replaces them. Then, for each module with non-empty newKeys, infer English from the key names, translate into cultures, and call sync_keys for THAT module (omit outputPath) — one sync_keys call per module produces one JSON file per module.
| Name | Required | Description | Default |
|---|---|---|---|
| refresh | No | Re-fetch tenant cultures from the API, bypassing the cache. | |
| diffBase | No | Git ref to diff against. Omit for uncommitted changes. | |
| framework | No | ||
| moduleName | No | Scope to a single Blocks module slug, e.g. "app-user-management". Omit to process every module present in the diff. | |
| extraModuleNames | No | Extra modules to exact-dedupe against. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It thoroughly explains the pipeline (scans working-tree + staged + untracked, groups by module prefix, fetches tenant cultures, exact-dedupes against module plus BLOCKS_DEDUP_MODULES) and the in-code nature (no LLM work). It also reveals the return structure. It doesn't mention side effects or auth requirements, but this is a read-only prep tool, so adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but front-loaded with the key message ('FIRST and usually ONLY prep call'). Every sentence contributes: scope, process, output, exclusions, and follow-up actions. It is dense but justified for a tool with this complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Without an output schema, the description explicitly defines the return value ({ cultures, modules: [{ module, newKeys, existingSkip }] }) and explains the full usage flow including subsequent sync_keys calls. It lacks edge-case details but is remarkably complete for a prep tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 80% with parameter descriptions for most fields. The description adds workflow-level context (e.g., 'Handles a diff spanning several modules in ONE call') and references dedupe modules, but most parameter details are already in the schema. It doesn't significantly elevate understanding beyond the schema, hence baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'The FIRST and usually ONLY prep call for a translation sync' and details its function: scanning the diff, grouping keys by module, fetching cultures, and exact-deduping. It explicitly distinguishes itself from siblings: 'Do NOT call find_keys / list_modules / list_cultures / search_keys separately — this replaces them.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use context ('FIRST and usually ONLY prep call') and when-not-to-use with named alternatives. It also prescribes the next steps: infer English, translate, then call sync_keys per module, omitting outputPath.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_keysSearch for existing Blocks keys (dedup check)A
Checks each key two ways before you upload it, no login required (public GetUilmFile endpoint): (1) exact KeyName match, and (2) same English text under a DIFFERENT KeyName (trimmed, case-insensitive) — catches e.g. adding "APP_X.SUBMIT" = "Submit" when "SUBMIT_TEXT" already = "Submit" elsewhere, so you reuse the existing key instead of creating a duplicate string. Checks the target module plus any modules in BLOCKS_DEDUP_MODULES (none by default). Pass extraModuleNames to widen it — e.g. shared modules that keys commonly leak into/from.
| Name | Required | Description | Default |
|---|---|---|---|
| keys | Yes | ||
| extraModuleNames | No | Additional module names to check beyond the target module and BLOCKS_DEDUP_MODULES. | |
| targetModuleName | Yes | Module name being worked on, e.g. "app-survey" (not a ModuleId). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full responsibility for behavioral disclosure. It reveals that no login is required (public endpoint), details the two distinct matching methods (exact KeyName and case-insensitive trimmed English text), explains the scope (target module + BLOCKS_DEDUP_MODULES), and notes how to widen it. This is rich contextual information beyond simple 'searches for keys'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-organized, starting with the core purpose and then expanding with numbered checks, an illustrative example, and scope details. It is longer than strictly necessary but every sentence contributes useful information, so it earns a 4 rather than 3.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (3 parameters, nested object array, no output schema, no annotations), the description covers the core behavior, use case, authentication, and parameter intent. It does not describe the return format or match result structure, which prevents a 5, but it is sufficiently complete for an agent to correctly select and invoke the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67%, with descriptions for targetModuleName, extraModuleNames, and englishText. The description adds value by explicitly tying targetModuleName to 'module being worked on', explaining extraModuleNames as a widening mechanism, and defining the matching semantics (trimmed, case-insensitive) that affect how the keys array is interpreted. This supplements the schema rather than repeating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource: 'Checks each key two ways before you upload it', immediately identifying it as a dedup-check tool for existing Blocks keys. The title and description together distinguish it from sibling tools like find_keys by emphasizing pre-upload duplicate detection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool ('before you upload it') and why ('so you reuse the existing key instead of creating a duplicate string'). It also explains how to broaden scope with extraModuleNames. However, it does not explicitly contrast with alternative tools like find_keys, leaving some room for interpretation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sync_keysDedup-check, build, and write a Blocks upload in one callA
The one-call path for adding new translation keys: resolves the module by name (cached to disk), dedup-checks every key against the target module + any BLOCKS_DEDUP_MODULES, skips any key whose exact KeyName already exists in the target module (would overwrite/duplicate), builds portal-ready upload entries for the rest, and — if outputPath is given — writes them straight to disk. Keys with the same English text under a DIFFERENT existing key are NOT auto-skipped (reusing them means changing the calling code, not this tool's call) — they come back in duplicateWarnings for you to decide on. Returns a compact summary, not the full entry JSON, to keep the response small — read the written file if you need the entries themselves. The upload JSON is written to outputPath, or — when you omit outputPath (recommended) — to the path from BLOCKS_OUTPUT_PATH_PATTERN with {module} substituted, resolved against the project root. Parent directories are created automatically. Do NOT invent an output path: omit outputPath and let the configured location be used.
| Name | Required | Description | Default |
|---|---|---|---|
| entries | Yes | ||
| tenantId | No | Defaults to BLOCKS_TENANT_ID from .env if omitted. | |
| moduleName | Yes | e.g. "app-survey" (not a ModuleId). | |
| outputPath | No | Where to write the upload JSON. Omit to use BLOCKS_OUTPUT_PATH_PATTERN (recommended). A relative path is resolved against the project root; parent dirs are created. | |
| extraModuleNames | No | Additional module names to dedup-check beyond the target module and BLOCKS_DEDUP_MODULES. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and exceeds expectations: it discloses dedup rules, exact-key skip behavior, duplicateWarnings, compact-summary response, path resolution via BLOCKS_OUTPUT_PATH_PATTERN, automatic parent directory creation, and the warning not to invent an output path. This is unusually transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every clause contributes a distinct behavioral fact. It is front-loaded with the core purpose and remains readable, though it could benefit from light bullet-point formatting for even faster scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, lack of output schema, and absence of annotations, the description covers all necessary context: return shape (compact summary, not full JSON), where to find the actual entries, output path rules, parent dir creation, dedup edge cases, and tenant default. It is self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is high (80%), the description adds significant parameter-level meaning: how outputPath behaves when omitted, how modules are resolved and dedup-checked against BLOCKS_DEDUP_MODULES, and how entries are processed (exact key skip vs duplicate-text warning). This goes well beyond the schema's bare field labels.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description is built around a specific verb-resource combination ('one-call path for adding new translation keys') followed by a clear step-by-step summary: resolve module, dedup-check, build entries, and write to disk. It distinguishes itself from siblings like build_upload_entries by emphasizing the write side and dedup logic, leaving no doubt about what this tool uniquely accomplishes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly frames itself as the single-call path for adding new keys and gives actionable advice (omit outputPath, do not invent an output path, call list_cultures first). It provides clear context for when to use it, though it does not name explicit alternatives or exclusions for sibling tools.
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.
7 tool updates
v0.1.0- First observed
build_upload_entries - First observed
find_keys - First observed
list_cultures - First observed
list_modules - First observed
prepare_sync - First observed
search_keys - First observed
sync_keys
TDQS
Scored across 7 tools
Each tool has a distinct purpose: finding new keys, listing cultures/modules, checking duplicates, building entries, and syncing. The main ambiguity is between find_keys, search_keys, and sync_keys, but the descriptions clearly differentiate them, and prepare_sync explicitly replaces the discovery tools for the common workflow.
All tool names follow a consistent verb_noun snake_case pattern (find_keys, list_cultures, build_upload_entries, prepare_sync). No mixed conventions or unpredictable naming.
7 tools is well within the ideal range and appropriately scoped for a translation synchronization workflow, covering discovery, dedup, and file generation without unnecessary bloat.
The tool set covers the core add-new-translation-keys workflow end-to-end: find, dedupe, prepare, and write upload files. Minor gaps include lack of an actual upload/publish tool and no way to fetch existing translations for editing, but these may be outside the server's intended scope.
Maintenance
Related MCP Connectors
Build and validate IndexNow payloads, check key files, and diff sitemaps into a submission list.
Scan configs, files, or text for leaked secrets and obvious misconfigurations. Nothing stored.
Generate SBOMs, scan vulnerabilities, and analyze dependencies from local projects or Git repos.
Scan code for quantum-vulnerable cryptography and get NIST post-quantum migration guidance.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables translation of JSON i18n files to multiple languages using various AI providers (Google Gemini, OpenAI, Ollama/DeepSeek) with intelligent caching and deduplication.16 npm5-
- AlicenseBqualityDmaintenanceProvides tools for working with iOS Localizable.xcstrings files, enabling automated translation workflows and localization management for iOS/macOS projects using Xcode String Catalogs.75MIT
- FlicenseAqualityDmaintenanceEnables automatic discovery and fast searching of translation files in projects, supporting partial/exact key-value matching with file watching and multiple translation file formats.2-
- FlicenseAqualityDmaintenanceExtracts text nodes from Figma designs and organizes them into structured JSON for internationalization workflows. It enables users to pull content from specific frames or entire files to automatically generate translation keys.1-