{"id":47913741,"url":"https://github.com/phrase/phrase-mcp-server","last_synced_at":"2026-05-13T15:02:15.229Z","repository":{"id":341009825,"uuid":"1157156123","full_name":"phrase/phrase-mcp-server","owner":"phrase","description":"Official Phrase MCP Server","archived":false,"fork":false,"pushed_at":"2026-04-02T15:20:54.000Z","size":439,"stargazers_count":3,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-02T23:04:31.518Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phrase.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T13:53:05.000Z","updated_at":"2026-04-02T13:34:17.000Z","dependencies_parsed_at":"2026-03-18T16:04:26.337Z","dependency_job_id":null,"html_url":"https://github.com/phrase/phrase-mcp-server","commit_stats":null,"previous_names":["phrase/phrase-mcp-server"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/phrase/phrase-mcp-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fphrase-mcp-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fphrase-mcp-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fphrase-mcp-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fphrase-mcp-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phrase","download_url":"https://codeload.github.com/phrase/phrase-mcp-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phrase%2Fphrase-mcp-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31389068,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T04:26:24.776Z","status":"ssl_error","status_checked_at":"2026-04-04T04:23:34.147Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-04T05:28:12.910Z","updated_at":"2026-05-13T15:02:15.223Z","avatar_url":"https://github.com/phrase.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Phrase MCP Server\n\nUse Phrase APIs from any MCP client (Claude, Cursor, etc.) with ready-to-use tools for Phrase Strings, Phrase TMS, and Connectors.\n\n## Who This Is For\n\n- Localization managers automating routine project and job operations\n- Engineers building AI workflows around Phrase\n- Teams that want one MCP server for both Strings and TMS\n- Teams that want one MCP server for Strings, TMS, and Connectors workflows\n\n### Available Tools\n\n#### Strings (`strings_*`)\n\n```text\nstrings_add_job_keys\nstrings_add_job_locale\nstrings_complete_job\nstrings_complete_job_locale\nstrings_compare_branch\nstrings_create_branch\nstrings_create_glossary\nstrings_create_glossary_term\nstrings_create_glossary_term_translation\nstrings_create_job\nstrings_create_job_comment\nstrings_create_job_template\nstrings_create_job_template_locale\nstrings_create_key\nstrings_create_locale\nstrings_create_locale_download\nstrings_create_project\nstrings_create_translation\nstrings_create_upload\nstrings_delete_branch\nstrings_delete_glossary_term\nstrings_delete_key\nstrings_delete_locale\nstrings_delete_project\nstrings_get_branch\nstrings_get_branch_comparison\nstrings_get_glossary\nstrings_get_glossary_term\nstrings_get_locale\nstrings_get_job\nstrings_get_job_comment\nstrings_get_job_locale\nstrings_get_job_template\nstrings_get_job_template_locale\nstrings_get_key\nstrings_get_locale_download\nstrings_get_project\nstrings_get_translation\nstrings_get_upload\nstrings_list_account_jobs\nstrings_list_branches\nstrings_list_formats\nstrings_list_glossaries\nstrings_list_glossary_terms\nstrings_list_job_comments\nstrings_list_job_locales\nstrings_list_job_template_locales\nstrings_list_job_templates\nstrings_list_jobs\nstrings_list_keys\nstrings_list_locales\nstrings_list_projects\nstrings_list_translations\nstrings_list_uploads\nstrings_lock_job\nstrings_merge_branch\nstrings_sync_branch\nstrings_remove_job_keys\nstrings_remove_job_locale\nstrings_reopen_job\nstrings_reopen_job_locale\nstrings_review_job_locale\nstrings_start_job\nstrings_unlock_job\nstrings_update_branch\nstrings_update_glossary\nstrings_update_glossary_term\nstrings_update_glossary_term_translation\nstrings_update_job\nstrings_update_job_locale\nstrings_update_key\nstrings_update_locale\nstrings_update_project\nstrings_update_translation\n```\n\n#### TMS (`tms_*`)\n\n```text\ntms_create_job_from_file\ntms_create_project\ntms_create_project_from_template\ntms_create_project_from_template_shorthand\ntms_download_target_file_async\ntms_evaluate_quality_profile\ntms_download_target_file_by_async_request\ntms_export_trans_memory\ntms_get_async_limits\ntms_get_async_request\ntms_get_job\ntms_get_project\ntms_get_project_template\ntms_get_termbase\ntms_get_trans_memory\ntms_import_trans_memory\ntms_list_jobs\ntms_list_pending_requests\ntms_list_project_templates\ntms_list_projects\ntms_list_termbases\ntms_list_trans_memories\ntms_search_job_termbases\ntms_search_jobs\ntms_search_termbase_terms\ntms_search_trans_memory\ntms_set_job_status\ntms_set_project_status\ntms_update_job\ntms_update_project\ntms_upload_termbase\n```\n\n#### Quality Evaluator (`bqe_*`)\n\n```text\nbqe_create_ai_check\nbqe_create_quality_profile\nbqe_delete_ai_check\nbqe_delete_quality_profile\nbqe_evaluate_segments\nbqe_get_ai_check\nbqe_get_analytics\nbqe_get_quality_profile\nbqe_list_ai_checks\nbqe_list_quality_profiles\nbqe_update_ai_check\nbqe_update_quality_profile\n```\n\n## Examples\n\nThe following examples build on each other as a complete end-to-end workflow: discover your projects, kick off a new translation with Phrase TMS, retrieve the result, and upload a localization file via Phrase Strings.\n\n### 1. List all projects\n\n**User prompt:** \"List all my Phrase projects\"\n\n**Expected behavior:**\n- Calls `tms_list_projects` and `strings_list_projects` in parallel\n- Returns all projects from both Phrase TMS and Phrase Strings\n\n**Expected output:**\n\n```\nPhrase TMS projects (3):\n- My Marketing Campaign (ID: ...) — en → de, fr — Status: COMPLETED\n- Product Documentation Q1 (ID: ...) — en → es — Status: NEW\n- Mobile App Strings (ID: ...) — en → ja, zh — Status: IN_PROGRESS\n\nPhrase Strings projects (2):\n- Web App (ID: ...) — Account: Acme Corp\n- Help Center (ID: ...) — Account: Acme Corp\n```\n\n### 2. Create a TMS project from a template and send a file for translation\n\n**User prompt:** \"Create a new TMS project from the tech documentation template and send the README for translation\"\n\n**Expected behavior:**\n- Calls `tms_list_project_templates` to resolve the template by name\n- Calls `tms_create_project_from_template_shorthand` to create the project\n- Calls `tms_create_job_from_file` to upload the file and create a translation job\n\n**Expected output:**\n\n```\nCreated TMS project \"README Translation\" (ID: ...)\n  Template: tech documentation\n  Source: en → Target: es\n  Status: NEW\n\nUploaded README.md as a translation job:\n  Job UID: ...\n  Target language: es\n  Status: NEW\n```\n\n### 3. Check translation status and download the completed file\n\n**User prompt:** \"Check if the README translation job is done and download the translated file\"\n\n**Expected behavior:**\n- Calls `tms_get_job` to check the current job status\n- Calls `tms_download_target_file_async` to trigger async file generation\n- Polls `tms_get_async_request` until the export is complete\n- Calls `tms_download_target_file_by_async_request` to retrieve and save the file\n\n**Expected output:**\n\n```\nJob \"README.md\"\n  Project: README Translation\n  Source: en → Target: es\n  Status: DELIVERED\n  Words: 535\n\nTriggering async export... done\nDownloading translated file... done\n\nSaved to: README.es.md\n```\n\n### 4. Create a Strings project and upload a localization file\n\n**User prompt:** \"Create a new Strings project and upload docs/examples/en.json (Format: simple_json) for localization\"\n\n**Expected behavior:**\n- Calls `strings_create_project` to create the project\n- Calls `strings_create_locale` to add the source locale\n- Calls `strings_create_upload` to upload the file and import translation keys\n- Calls `strings_get_upload` to confirm the upload succeeded\n\n**Expected output:**\n\n```\nCreated Strings project \"My App Config\" (ID: ...)\n  Account: Acme Corp\n\nAdded locale: English (en) — main locale\n\nUploading en.json (format: simple_json)... done\n  Upload state: success\n  Translation keys created: 14\n  Translations created: 14\n```\n\n#### Connectors (`connectors_*`)\n\n```text\nconnectors_download_raw\nconnectors_list_connectors\nconnectors_list_content\nconnectors_upload_raw\n```\n\n## Prerequisites\n\n- Node.js 20+\n\n## Quick Start\n\n### Add to your MCP client\n\nUse the published package with `npx` in your MCP client config.\n\n#### Codex (`~/.codex/config.toml`)\n\n```toml\n[mcp_servers.phrase]\ncommand = \"npx\"\nargs = [\"-y\", \"@phrase/phrase-mcp-server\"]\n\n[mcp_servers.phrase.env]\nPHRASE_STRINGS_TOKEN = \"your_token\" # Required for Strings tools, optional for TMS-only usage\nPHRASE_TMS_TOKEN = \"your_token\" # Required for TMS tools, optional for Strings-only usage\nPHRASE_CONNECTORS_TOKEN = \"your_token\" # Required for Connectors tools\nPHRASE_ENABLED_PRODUCTS = \"strings,tms,connectors\" # Optional, defaults to all products\nPHRASE_REGION = \"eu\"\n```\n\n#### Claude Desktop (`claude_desktop_config.json`)\n\n```json\n{\n  \"mcpServers\": {\n    \"phrase\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@phrase/phrase-mcp-server\"],\n      \"env\": {\n        \"PHRASE_STRINGS_TOKEN\": \"your_token\",\n        \"PHRASE_TMS_TOKEN\": \"your_token\",\n        \"PHRASE_CONNECTORS_TOKEN\": \"your_token\",\n        \"PHRASE_ENABLED_PRODUCTS\": \"strings,tms,connectors\",\n        \"PHRASE_REGION\": \"eu\"\n      }\n    }\n  }\n}\n```\n\nSet at least one product token in your MCP client config:\n\n- Minimum Strings setup:\n  - `PHRASE_STRINGS_TOKEN=your_token`\n  - `PHRASE_REGION=eu`\n- Strings + TMS setup:\n  - `PHRASE_STRINGS_TOKEN=your_token`\n  - `PHRASE_TMS_TOKEN=your_token`\n  - `PHRASE_REGION=eu`\n- Connectors setup:\n  - `PHRASE_CONNECTORS_TOKEN=your_token`\n  - `PHRASE_REGION=eu`\n\n## Configuration Reference\n\n### Product selection\n\n- `PHRASE_ENABLED_PRODUCTS`: comma-separated subset of `strings,tms,bqe,connectors`\n- `PHRASE_DISABLED_PRODUCTS`: products removed from the enabled set\n- Default behavior: all products enabled\n\n### Region selection\n\n- Global:\n  - `PHRASE_REGION`: `eu` or `us` (default `eu`)\n\n### Authentication\n\nThe server uses [Phrase Platform API tokens](https://developers.phrase.com/en/api/platform/authentication). You need to create API tokens in your Phrase account and provide them as environment variables to the MCP server.\n\n- Per product (`STRINGS`, `TMS`, etc.):\n  - `PHRASE_\u003cPRODUCT\u003e_TOKEN`\n\n### Connectors notes\n\n- Connectors v1 currently supports only `google-drive`.\n- Connectors base URLs are built in and selected by `PHRASE_REGION`:\n  - `eu` -\u003e `https://eu.phrase.com/connectors`\n  - `us` -\u003e `https://us.phrase.com/connectors`\n- Only stored Phrase connector credentials are supported in v1. Pass `request.connectorUuid`; inline `googleDrive2Credentials` are rejected.\n- `request.configuration` is required and must be an object. Today it is forwarded as-is and is usually `{}`, but the wrapper still requires it because the upstream connector contract does.\n- The `request.path` object is the main Google Drive contract. The wrapper only validates or normalizes a few cases and otherwise forwards the path unchanged.\n- Google Drive list operations default to `{ \"pathType\": \"ROOT\" }` when `request.path` is omitted.\n- Google Drive requests default `locale` to `en` when the caller does not provide one.\n- Google Drive uploads use the connector's direct stream-upload flow from `file_path`; Connectors file storage is not used in v1.\n- XLIFF and async endpoints are intentionally out of scope in v1.\n\nPath model summary:\n\n- `ROOT`: connector navigation root. Use it for the first list call; it exposes entries such as My Drive and Shared drives.\n- `SHARED_DRIVES_ROOT`: shared-drive picker. Use it to enumerate available shared drives.\n- `FOLDER`: concrete folder listing target. Use it for list calls inside My Drive or a shared drive.\n- `FILE`: concrete file target. Use it for downloads and as the final target shape for uploads.\n\nDrive model summary:\n\n- My Drive paths use `\"drive\": { \"driveType\": \"MY_DRIVE\" }`.\n- Shared drive paths use `\"drive\": { \"driveType\": \"SHARED_DRIVE\", \"driveId\": \"...\" }`.\n- `parentChain` describes the ancestry of the file or folder within the drive. For list calls at the top of a drive it is usually `[]`. For file operations it points at the parent folders of the file.\n\nMCP wrapper behavior:\n\n- `connectors_list_content`:\n  - defaults to `ROOT` when `request.path` is omitted\n  - still requires `request.configuration`, which is usually `{}`\n  - otherwise forwards the provided path unchanged\n- `connectors_download_raw`:\n  - requires an explicit `FILE` path\n  - returns inline bytes plus optional `saved_to` instead of storing content in Connectors file storage\n- `connectors_upload_raw`:\n  - reads bytes from local `file_path`\n  - rejects `request.storageId` because file storage uploads are out of scope in v1\n  - fills `request.name` from the local filename when omitted\n  - overwrites `request.size` with the actual file size\n  - native Google Drive upload semantics expect a destination `FILE` path that includes the filename\n  - accepts a `FOLDER` path as a convenience and rewrites it into a `FILE` path by appending the folder to `parentChain` and filling the filename from `request.name` or `file_path`\n  - performs the upstream stream registration and `PUT` internally, even though MCP exposes it as one upload tool call\n\nFor a detailed Google Drive path and configuration guide, including Bruno-aligned examples and the exact MCP normalization rules, see [docs/developer/connectors-google-drive.md](docs/developer/connectors-google-drive.md).\n\nExample root listing:\n\n```json\n{\n  \"connector\": \"google-drive\",\n  \"request\": {\n    \"connectorUuid\": \"8d6655d6-1be2-46af-89c0-7615866d2523\",\n    \"configuration\": {}\n  }\n}\n```\n\nExample upload from a local file:\n\n```json\n{\n  \"connector\": \"google-drive\",\n  \"file_path\": \"./demo.txt\",\n  \"request\": {\n    \"connectorUuid\": \"8d6655d6-1be2-46af-89c0-7615866d2523\",\n    \"configuration\": {},\n    \"path\": {\n      \"pathType\": \"FOLDER\",\n      \"folderId\": \"root\",\n      \"drive\": { \"driveType\": \"MY_DRIVE\" },\n      \"parentChain\": []\n    }\n  }\n}\n```\n\n### Security recommendations\n\n- Use a dedicated service user token for automation\n- Prefer least-privilege project manager permissions over admin-level roles\n\n## Privacy Policy\n\nThis server connects to Phrase APIs on your behalf using the credentials you provide. No data is collected or stored by this server itself. See the [Phrase Privacy Policy](https://phrase.com/privacy) for details on how Phrase handles your data.\n\n## Developer Documentation\n\nFor maintainer-facing docs, see:\n\n- [Developer docs index](docs/developer/README.md)\n- [Running published vs local builds](docs/developer/running.md)\n- [Releasing](docs/developer/releasing.md)\n\n## Support\n\nFor support, please [open an issue on GitHub](https://github.com/phrase/phrase-mcp-server/issues) or [submit a request](https://support.phrase.com/hc/requests/new) via Phrase Help Center.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphrase%2Fphrase-mcp-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphrase%2Fphrase-mcp-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphrase%2Fphrase-mcp-server/lists"}