npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

localization-mcp-server

v1.3.14

Published

MCP server for the localization system — controlled AI access to translations

Readme

localization-mcp-server

MCP server for the localization backend. Provides controlled AI access to translations: reading, editing, quality checks, sandbox workflow, project management, webhooks, and more.

Installation

npm install -g localization-mcp-server

Configuration

| Variable | Required | Description | |----------|----------|-------------| | MCP_TOKEN | Yes | API token for backend authentication | | BACKEND_URL | Yes | Base URL of the localization backend (e.g. http://79.76.35.167:8080) | | ADMIN_UI_URL | No | Admin UI URL for links in tool responses | | NODE_ENV | No | In non-production mode, loads .env from the package directory | | AUDIT_LOG_PATH | No | Path for write-operation audit log (default: ./mcp-audit.log) |

Copy .env.example as a starting point.

Environment safety (mandatory)

Dynamic environment resolution is a core requirement, not optional.

The developer configuring this MCP server is responsible for wiring BACKEND_URL to the correct environment. The server does not auto-detect which environment it should target.

Rules:

  1. BACKEND_URL must always be set explicitly. If missing, the server logs a loud warning and refuses to start. Always point to the production backend.

  2. Never hardcode production URLs in MCP config that is also used during development. Use environment-specific .env files or inject BACKEND_URL from your CI/runtime config.

  3. Development agents should work with sandbox. All MCP write tools target sandbox only — production is read-only. But BACKEND_URL still determines which server's sandbox you hit.

  4. If environment is unknown, fail safely. Do not silently guess production. The server will show (NOT SET) in diagnostic output if BACKEND_URL is missing, making misconfiguration visible.

  5. Each environment needs its own MCP_TOKEN. Tokens are server-specific — a dev token won't work on production and vice versa.

Correct setup:

BACKEND_URL=http://79.76.35.167:8080
ADMIN_UI_URL=http://79.76.35.167:3010

URL disambiguation for agents

| Purpose | URL | Notes | |---------|-----|-------| | Backend API (for all MCP/agent requests) | http://79.76.35.167:8080 | All tool calls go here | | Admin UI (browser only, not for API calls) | http://79.76.35.167:3010 | Human-facing UI, do NOT send API requests here | | Swagger docs | http://79.76.35.167:8080/api-docs | API reference |

Agents must:

  • Use the configured BACKEND_URL for all API requests
  • Never send API requests to ADMIN_UI_URL (port 3010) — it serves static HTML, not the API
  • Never guess ports — use the exact URL from environment config
  • If BACKEND_URL is not configured, surface the error instead of improvising

Usage

Start the MCP server over stdio:

localization-mcp-server

Run the interactive setup helper:

localization-mcp-server setup

Claude Code / Cursor integration

Add to your MCP config (.mcp.json or ~/.claude.json):

{
  "mcpServers": {
    "localization": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "localization-mcp-server"],
      "env": {
        "MCP_TOKEN": "<your-token>",
        "BACKEND_URL": "http://79.76.35.167:8080"
      }
    }
  }
}

CLI registration (recommended)

claude mcp add -s user localization \
  -e MCP_TOKEN=your-token \
  -e BACKEND_URL=http://79.76.35.167:8080 \
  -- npx -y localization-mcp-server

Warning: Always register globally with -s user. Per-project registration (without -s user) creates a .mcp.json in the current directory that overrides the global config. This causes 401 errors in every other project because they pick up the override without the correct token. If you see unexpected 401s, run:

claude mcp remove localization && claude mcp add -s user localization -e MCP_TOKEN=<token> -e BACKEND_URL=<url> -- npx -y localization-mcp-server

Available Tools (38 total)

Discovery

| Tool | Description | Parameters | |------|-------------|------------| | assess_integration_state | Full integration assessment with agent guide, URL patterns, and project details | projectSlug? | | list_projects | List all projects with sandbox state | — | | get_project_details | Namespaces, locales, sandbox status for a project | projectSlug |

Project Structure

Projects, namespaces, locales, and webhooks — structural setup, not translation content.

| Tool | Description | Key Parameters | |------|-------------|----------------| | create_project | Create a new project | slug, name? | | create_namespace | Create a namespace (requires reason justification) | projectSlug, namespace, reason | | rename_namespace | Rename an existing namespace | projectSlug, currentSlug, newSlug | | delete_namespace | Delete namespace with all keys (requires confirmed: true) | projectSlug, namespace, confirmed | | create_locale | Add a locale to a project | projectSlug, code, isDefault? | | update_locale | Update locale aliases | projectSlug, code, aliases | | delete_locale | Remove locale and all its values (requires confirmed: true) | projectSlug, code, confirmed | | list_webhooks | List webhook configs for a project | projectSlug | | create_webhook | Register outgoing webhook | projectSlug, url, events, description?, secret? | | update_webhook | Update webhook config | projectSlug, webhookId, url?, events?, enabled? | | delete_webhook | Delete a webhook | projectSlug, webhookId | | list_webhook_events | List supported event types | — |

Translations — Read

| Tool | Description | Key Parameters | |------|-------------|----------------| | list_translations | Browse entries with search, pagination, quality/locale filters | projectSlug, namespace, env, search?, missingLocale?, qualityLevel? | | get_translations_needing_attention | Get non-green translations that need quality improvement | projectSlug, namespace, qualityLevels?, includeUnchecked? | | export_namespace | Full JSON export per locale | projectSlug, namespace, env?, locale? | | get_namespace_coverage | Per-locale fill percentage with missing key samples | projectSlug, namespace, env? | | compare_local_vs_server | Diff local JSON against server entries | projectSlug, namespace, translations?, filePath?, env? | | analyze_entries | Preflight analysis of planned keys — duplicates, conflicts, reuse signals | projectSlug, namespace, entries, sourceLocale? | | check_keys_exist | Check if a list of keys exist in a namespace | projectSlug, namespace, keys, env? |

Translations — Write

All writes go to the sandbox. Production is read-only from MCP.

| Tool | Description | Key Parameters | |------|-------------|----------------| | set_translation | Create or update one key (upsert). Only passed locales are changed. | projectSlug, namespace, key, values, context? | | delete_translation | Soft delete a key in sandbox | projectSlug, namespace, key | | rename_key | Rename a key preserving all values | projectSlug, namespace, oldKey, newKey | | mark_expected | Mark a locale translation as manually accepted (suppresses quality warnings) | projectSlug, namespace, key, locale | | unmark_expected | Remove manual acceptance from a locale translation | projectSlug, namespace, key, locale | | revert_sandbox_entry | Revert a single key to its production value | projectSlug, namespace, key |

Translations — Bulk Write

| Tool | Description | Key Parameters | |------|-------------|----------------| | bulk_set_locale | Bulk upsert many keys for a single locale | projectSlug, namespace, locale, entries, dryRun? | | bulk_import | Multi-locale bulk upsert from inline JSON or file path | projectSlug, namespace, translations?, filePath?, contexts?, dryRun? |

AI

| Tool | Description | Key Parameters | |------|-------------|----------------| | ai_translate | Translate one text to project locales via Gemini (does not save) | projectSlug, text, context?, targetLocales? | | bulk_ai_translate | Translate N keys in one call — batches of 10 (does not save) | projectSlug, entries, targetLocales? | | bulk_translate_and_save | Translate N keys, save to sandbox, and quality-check in one step | projectSlug, namespace, entries, targetLocales?, skipQuality? | | ai_quality_check | Stateless multi-locale quality check — score, level, comment (not persisted) | projectSlug, source, translations: {locale: string}, context? | | check_entry_quality | Quality check all locales of a key and persist results to DB | projectSlug, namespace, key | | get_ai_usage | AI token usage statistics for a project | projectSlug |

Sandbox & Promotion

| Tool | Description | Parameters | |------|-------------|------------| | reset_sandbox | Discard all sandbox changes (requires confirmed: true) | projectSlug, confirmed | | get_translation_diff | Full diff between sandbox and production | projectSlug, namespace?, locale?, statusFilter? | | validate_translations | Analyze diff for empty values, partial translations, deletions | projectSlug, namespace? | | preview_push_to_production | Read-only preview of what would change on promote | projectSlug | | list_snapshots | List available production snapshots | projectSlug |

Note: Promoting sandbox to production is intentionally not available via MCP. Use the Admin UI.


Workflows

Starting a session

Before writing to any project:

1. list_projects                          → confirm project exists
2. get_project_details(projectSlug)       → get namespaces, locales, sandbox state
   → sandbox auto-initializes on project creation; use reset_sandbox if re-sync needed
3. [start writing]

Adding translations for a new locale

1. get_project_details("my-app")          → confirm locale doesn't exist
2. create_locale("my-app", "nb-NO")       → add the locale
3. get_namespace_coverage("my-app", "common") → see fill gaps
4. list_translations("my-app", "common", { missingLocale: "nb-NO" })
5. bulk_set_locale("my-app", "common", "nb-NO", entries)
6. validate_translations("my-app")        → check for issues
7. preview_push_to_production("my-app")   → review before promoting

Importing translations from a local file

1. compare_local_vs_server("my-app", "common", { filePath: "/path/to/en.json" })
   → see what's new, matching, or conflicting
2. bulk_import("my-app", "common", { filePath: "/path/to/translations.json", dryRun: true })
   → preview what would be imported
3. bulk_import("my-app", "common", { filePath: "/path/to/translations.json" })
   → actually import
4. get_translation_diff("my-app")         → verify changes

Bulk translate and save new keys

1. get_project_details("my-app")          → confirm namespace + locales
   → sandbox auto-initializes on project creation; use reset_sandbox to re-sync if needed
2. bulk_translate_and_save("my-app", "common", entries)
   → translates, saves to sandbox, and returns inline quality scores
3. Fix any red translations via set_translation
4. preview_push_to_production("my-app")   → review before promoting

Quality improvement workflow

1. get_translations_needing_attention("my-app", "common")
   → find yellow/red translations
2. For each problematic key:
   - Review context and values
   - set_translation to fix the value, OR
   - mark_expected if the translation is actually correct
3. check_entry_quality("my-app", "common", "button.save")
   → re-check and persist updated quality scores

Integrating a new project (from a consumer app)

1. assess_integration_state("my-app")     → get full diagnosis
   → returns: URL patterns, classification guide, project state
2. Follow the guide for your integration state (S1-S6)
3. Update local app config to point to the backend

Safety Rules

Destructive operations (require explicit user instruction)

| Tool | Risk | |------|------| | reset_sandbox | Wipes all pending sandbox changes | | delete_translation | Removes a key and all its values | | delete_locale | Removes a locale across ALL namespaces | | delete_namespace | Removes a namespace and ALL its keys | | bulk_import with overwrite | Can silently overwrite existing translations |

Locale code rules

  • Always use exact BCP 47 codes from get_project_details
  • Never guess or remap: nb-NO is not no, da-DK is not da
  • Invalid codes are rejected with a clear error

Namespace policy

  • Always check existing namespaces before creating a new one
  • create_namespace requires a reason explaining why no existing namespace fits
  • If the target namespace is ambiguous, ask the user — don't guess

Key naming

Keys must match: /^[a-zA-Z0-9._-]+$/

Valid: button.save, error-message, form_field Invalid: button/save, button save, button:save


Production Model

  • All MCP writes go to sandbox only
  • Production is read-only from MCP
  • Promoting to production is a manual step via Admin UI
  • preview_push_to_production shows what would change but does NOT push

Published Files

The package publishes dist/, flows/, .env.example, and this README.