Skip to content
better-i18n.com
Bu sayfada

Better i18n provides two MCP servers with focused toolsets. All project-scoped tools require a project parameter in org/project format (e.g., "aliosman-co/personal").

Translation Tools (@better-i18n/mcp) #

Discovery Tools #

List all projects you have access to across all organizations.

Use this first to discover available projects before other operations.

Returns: Project slugs, source/target languages, organization names.

Get project details including namespaces, languages, key count, and translation coverage.

Returns: Namespaces, languages with coverage percentages, total key count.

Reading Tools #

Browse translation keys in compact, paginated format. Optimized for exploration — use getTranslations when you need actual translation text for AI tasks.

Parameters:

  • search (optional): Search key names by partial match. Single string or array for multi-term OR search (e.g., ["login", "signup"]).
  • namespaces (optional): Filter by specific namespaces (e.g., ["auth", "common"]).
  • missingLanguage (optional): Return only keys that DON'T have a translation for this language code (e.g. "tr", "zh-Hans").
  • fields (optional): Fields to include per key. Default: ["id", "sourceText"].
    • "translatedLanguageCount"tlc: 5 — token-efficient count, ideal for coverage overview
    • "translatedLanguages"tl: ["de","fr","tr"] — full list of translated lang codes
    • "translations"tr: {"de":"..."} — actual translation text (heaviest)
  • page (optional): Page number, 1-indexed (default: 1).
  • limit (optional): Keys per page, max 100 (default: 20).

Response format (compact):

  • tot: total matching keys | ret: returned this page | has_more: more pages exist
  • nss: namespace lookup table — each key's ns is an index into this array
  • k: key items with k (name), ns (namespace index), and requested fields

Examples:

JSON
// Browse first page
{ "project": "org/project" }

// Find keys missing Turkish
{ "project": "org/project", "missingLanguage": "tr" }

// Coverage overview (token-efficient)
{ "project": "org/project", "fields": ["id", "translatedLanguageCount"] }

// Search with full language list
{ "project": "org/project", "search": "login", "fields": ["id", "sourceText", "translatedLanguages"] }

Writing Tools #

Create one or more translation keys with source text and optional target translations.

Parameters:

  • keys: Array of keys to create:
    • name: Key name (e.g., "submit_button", "nav.home")
    • namespace: Namespace (optional, default: "default")
    • sourceText: Source language text
    • translations: Target translations object (e.g., { "tr": "Gönder", "de": "Senden" })

Source language text goes in sourceText, not in translations.

JSON
{
  "keys": [
    {
      "name": "auth.login.title",
      "namespace": "common",
      "sourceText": "Sign In",
      "translations": { "tr": "Giriş Yap" }
    }
  ]
}

Update source text and/or target translations. Each entry updates ONE language for ONE key.

Parameters:

  • translations: Array of translation updates:
    • key: Key name (e.g., "submit_button")
    • namespace: Namespace (optional, default: "default")
    • language: Language code (e.g., "en", "tr", "de")
    • text: New text value
    • isSource: Set true to update source text (optional)
    • status: "published", "pending", "reviewed" (optional, default: "published")
JSON
{
  "translations": [
    { "key": "auth.login.title", "language": "en", "text": "Sign In", "isSource": true },
    { "key": "auth.login.title", "language": "tr", "text": "Giriş Yap" }
  ]
}

Soft-delete translation keys by UUID. Keys are removed from CDN/GitHub on next publish.

Parameters:

  • keyIds: Array of key UUIDs (1-100). Get UUIDs from listKeys.

Add one or more target languages to the project. Already-existing languages are silently skipped.

Parameters:

  • languages: Array of languages to add (1–50):
    • languageCode: ISO 639-1 code (e.g. "fr", "ja") or BCP 47 locale (e.g. "zh-Hans", "pt-BR")
    • status (optional): "active" (published to CDN, default) or "draft" (visible but not deployed)
JSON
{
  "languages": [
    { "languageCode": "tr", "status": "active" },
    { "languageCode": "zh-Hans" }
  ]
}

Update the status of existing target languages — activate, deactivate, or archive them.

Parameters:

  • edits: Array of status changes (1–50):
    • languageCode: ISO 639-1 or BCP 47 locale code of the language
    • newStatus: "active" (published to CDN), "draft" (visible but not deployed), or "archived" (hidden from editor and CDN)
JSON
{
  "edits": [
    { "languageCode": "de", "newStatus": "active" },
    { "languageCode": "zh-Hans", "newStatus": "archived" }
  ]
}

Publish Tools #

Preview what will be deployed before publishing. Shows translations, deleted keys, and publish destination.

Returns:

  • hasPendingChanges: Boolean indicating if there's anything to publish
  • summary: Object with translation counts, deleted keys, and total changes
  • byLanguage: Breakdown of pending translations by language code
  • deletedKeys: Keys that will be permanently removed on publish
  • publishDestination: "github", "cdn", or "none"
  • cannotPublishReason: Error message if publishing is blocked

Workflow:

  1. Call getPendingChanges to see what's pending
  2. Review the changes
  3. Call publishTranslations only if changes look correct

Deploy pending changes to production (CDN or GitHub). Returns immediately with sync job IDs for tracking.

Parameters:

  • translations (optional): Array of specific translations to publish with keyId and languageCode. If omitted, publishes ALL pending changes.

Returns:

  • success: Boolean indicating if publish was initiated
  • published: Number of translations published
  • repositories: Number of repositories updated
  • syncJobIds: Array of sync job IDs for tracking with getSync

Important:

  • This is an async operation - jobs typically complete in 5-30 seconds
  • Use getSync(syncId) to verify completion
  • Deleted keys are permanently removed from CDN/GitHub and database
JSON
{
  "translations": [
    { "keyId": "uuid-1", "languageCode": "tr" },
    { "keyId": "uuid-2", "languageCode": "de" }
  ]
}

Sync Tools #

List recent sync operations for a project.

Parameters:

  • limit (optional): Max results (default: 10, max: 50)
  • status (optional): "pending", "in_progress", "completed", "failed"
  • type (optional): "initial_import", "source_sync", "cdn_upload", "batch_publish"

Get details about a specific sync operation including logs and affected keys.

Parameters:

  • syncId: Sync job ID from getSyncs or publishTranslations response.

Returns:

  • id: Sync job ID
  • type: Job type (e.g., "batch_publish")
  • status: "completed", "failed", "in_progress", "pending", "cancelled"
  • startedAt: ISO timestamp
  • completedAt: ISO timestamp (null if still running)
  • errorMessage: Error details if failed
  • logs: Array of log messages
  • affectedKeys: Keys modified in this sync

Content Tools (@better-i18n/mcp-content) #

These tools manage headless CMS content — models, entries, and localized content fields.

Model Tools #

List all content models in a project with entry counts.

Returns: Array of models with slug, displayName, entryCount, and field definitions.

Get a content model's full details including all field definitions.

Parameters:

  • modelSlug: The model's URL slug (e.g., "blog-post")

Returns: Model with fields, each containing name, type, required, description.

Create a new content model with optional initial field definitions.

Parameters:

  • slug: Model slug (lowercase, hyphens only, e.g., "blog-posts")
  • displayName: Human-readable model name
  • description (optional): Model description
  • kind (optional): "collection" (multiple entries, default) or "single" (one entry)
  • icon (optional): Icon identifier
  • enableVersionHistory (optional): Enable version history tracking (default: true)
  • fields (optional): Array of initial field definitions with name, displayName, type, localized, required, options, fieldConfig
JSON
{
  "slug": "blog-posts",
  "displayName": "Blog Posts",
  "kind": "collection",
  "fields": [
    { "name": "author_name", "displayName": "Author", "type": "text", "required": true },
    { "name": "category", "displayName": "Category", "type": "enum", "options": { "enumValues": [{ "label": "Tech", "value": "tech" }] } }
  ]
}

Update a content model's metadata, including display settings.

Parameters:

  • modelSlug: Content model slug to update
  • displayName (optional): Updated display name
  • description (optional): Updated description
  • kind (optional): Updated model kind ("collection" or "single")
  • icon (optional): Updated icon identifier
  • enableVersionHistory (optional): Updated version history setting
  • tableSettings (optional): Table display settings for base field column visibility
    • baseFields: Map of base field name → show in table (e.g., { "title": true, "slug": false, "body": false })

Delete a content model and all its entries.

Parameters:

  • modelSlug: Content model slug to delete

Warning: This permanently deletes the model and all associated entries, fields, and content.

Field Tools #

Add a custom field to a content model. Field name must be snake_case.

Parameters:

  • modelSlug: Parent content model slug
  • name: Field name (snake_case, e.g., "author_name")
  • displayName: Display name (e.g., "Author Name")
  • type (optional): Field type — text, textarea, richtext, number, boolean, date, datetime, enum, media, relation (default: text)
  • localized (optional): Whether field is localized per language (default: false)
  • required (optional): Whether field is required (default: false)
  • placeholder (optional): Placeholder text
  • helpText (optional): Help text
  • position (optional): Sort position (auto-calculated if omitted)
  • options (optional): Field-level options
    • enumValues: Allowed values for enum fields — [{ "label": "Display", "value": "stored" }]
    • showInTable: Whether this field appears as a column in the content list table
    • unsplash: { "enabled": true } for Unsplash integration
    • aiGeneration: { "enabled": true, "prompt": "..." } for AI generation
  • fieldConfig (optional): Type-specific configuration
    • targetModel: Target model slug for relation fields

There is no array or group field type. To model repeating content, do not create numbered fields (feature_1, feature_2, tag_1_slug…) — that is an anti-pattern. Use a body block (code-first, registered per project, backed by a JSON Schema that supports arrays/nested objects, inserted via the / slash picker) for page-composition repetition, or a relation field for references to other entries.

Update a custom field's properties within a content model.

Parameters:

  • modelSlug: Parent content model slug
  • fieldName: Field name to update
  • displayName (optional): Updated display name
  • type (optional): Updated field type
  • localized (optional): Updated localization setting
  • required (optional): Updated required setting
  • placeholder (optional): Updated placeholder text
  • helpText (optional): Updated help text
  • options (optional): Updated field-level options
    • enumValues: Updated allowed values for enum fields
    • showInTable: Whether this field appears as a column in the content list table
    • unsplash: Updated Unsplash settings
    • aiGeneration: Updated AI generation settings
  • fieldConfig (optional): Updated type-specific configuration

Remove a custom field from a content model.

Parameters:

  • modelSlug: Parent content model slug
  • fieldName: Field name to remove

Warning: This permanently removes the field and all its values from existing entries.

Reorder custom fields in a content model.

Parameters:

  • modelSlug: Parent content model slug
  • fieldNames: Array of field names in desired order

Entry Tools #

List content entries with filtering and pagination.

Parameters:

  • modelSlug (optional): Filter by content model
  • search (optional): Text search across title and body
  • language (optional): Language code for translated content
  • status (optional): "draft", "published", or "archived"
  • missingLanguage (optional): Return entries that don't have a translation for this language code
  • searchLanguages (optional): Array of language codes to search across when using search
  • searchInBody (optional): Whether to include body content in text search (default: false)
  • expand (optional): Additional fields to include in the response (e.g., ["customFields", "translations"])
  • compact (optional): Return minimal fields only (default: false)

Returns: Paginated list of entries with id, slug, title, status, publishedAt.

Get a single content entry with all translations and custom field values.

Parameters:

  • entryId: The entry UUID

Returns: Full entry with title, body, bodyMarkdown, bodyHtml, translations, customFields.

Create a new content entry in a model.

Parameters:

  • modelSlug: Target content model slug
  • title: Entry title
  • slug (optional): URL slug (auto-generated from title if omitted)
  • bodyMarkdown (optional): Entry body as Markdown (automatically converted to HTML and editor JSON)
  • translations (optional): Map of language code → title for multi-language support (e.g., { "en": "Hello", "tr": "Merhaba" })
JSON
{
  "modelSlug": "blog-post",
  "title": "Getting Started with i18n",
  "bodyMarkdown": "# Welcome\n\nThis guide covers...",
  "translations": { "en": "Getting Started with i18n", "tr": "i18n'e Başlarken" }
}

Update an existing content entry's translations or metadata.

Parameters:

  • entryId: The entry UUID
  • languageCode: Language to update
  • title (optional): Updated title
  • bodyMarkdown (optional): Updated body as Markdown
  • excerpt (optional): Short summary
  • metaTitle (optional): SEO title
  • metaDescription (optional): SEO description

Duplicate an existing content entry within the same model.

Parameters:

  • entryId: Source entry UUID to duplicate

Returns: Newly created entry with a generated slug (original slug + -copy).

Publish Tools #

Publish a content entry to CDN. Sets status to "published" and triggers async CDN upload.

Parameters:

  • entryId: The entry UUID

Returns: Updated entry with publishedAt timestamp.

Hard-delete a content entry (irreversible).

Parameters:

  • entryId: The entry UUID

Warning: This permanently deletes the entry and all its translations. This action cannot be undone.

Create multiple content entries in a single model at once (max 20). Partial success is possible — response reports created count and any failures.

Parameters:

  • modelSlug: Content model slug (required)
  • entries: Array of entry objects (1–20), each with:
    • title: Entry title (required)
    • slug: URL slug (required)
    • bodyMarkdown (optional): Body content as Markdown
    • status (optional): "draft" or "published" (default: "draft")
    • customFields (optional): Custom field values
    • translations (optional): Map of language code → { title, bodyMarkdown, customFields }

Returns: { created: number, failed: number, entries: [...], errors: [...] }

Publish multiple content entries at once.

Parameters:

  • entryIds: Array of entry UUIDs to publish (required)
  • modelSlug (optional): Content model slug (for context/validation only — not required)

Returns: Array of published entries with updated publishedAt timestamps.


Best Practices #

  1. Discover First: Start with listProjectsgetProject to understand the project.
  2. Find Gaps: Use listKeys to see all keys and find missing translations.
  3. Batch Operations: createKeys and updateKeys handle single and bulk operations efficiently.
  4. Source Text: Use updateKeys with isSource: true to update source text.
  5. Clean Up: Use deleteKeys to remove unused keys (soft delete until publish).
  6. Safe Publishing: Always call getPendingChanges before publishTranslations to verify changes.
  7. Track Deployment: Use getSync(syncId) to verify publish jobs completed successfully.
  8. Language Setup: Use proposeLanguages to add new languages, proposeLanguageEdits to change status (active/draft/archived).