lokalise-mcp
Version:
The Lokalise MCP Server brings Lokalise's localization power to Claude and AI assistants—manage projects, keys, and translations by chat.
214 lines (213 loc) • 11.6 kB
JavaScript
import { formatErrorForMcpTool } from "../../shared/utils/error.util.js";
import { Logger } from "../../shared/utils/logger.util.js";
import languagesController from "./languages.controller.js";
import { AddProjectLanguagesToolArgs, GetLanguageToolArgs, ListProjectLanguagesToolArgs, ListSystemLanguagesToolArgs, RemoveLanguageToolArgs, UpdateLanguageToolArgs, } from "./languages.types.js";
/**
* @function handleListSystemLanguages
* @description MCP Tool handler to retrieve a list of system languages from Lokalise.
* It calls the languagesController to fetch the data and formats the response for the MCP.
*
* @param {ListSystemLanguagesToolArgsType} args - Arguments provided to the tool.
* @returns {Promise<{ content: Array<{ type: 'text', text: string }> }>} Formatted response for the MCP.
* @throws {McpError} Formatted error if the controller or service layer encounters an issue.
*/
async function handleListSystemLanguages(args) {
const methodLogger = Logger.forContext("tools/languages.tool.ts", "handleListSystemLanguages");
methodLogger.debug(`Getting Lokalise system languages list (limit: ${args.limit || "default"}, page: ${args.page || "1"})...`, args);
try {
// Pass args directly to the controller
const result = await languagesController.listSystemLanguages(args);
methodLogger.debug("Got the response from the controller", result);
// Format the response for the MCP tool
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error("Error getting Lokalise system languages list", error);
return formatErrorForMcpTool(error);
}
}
/**
* @function handleListProjectLanguages
* @description MCP Tool handler to retrieve a list of languages for a specific Lokalise project.
* It calls the languagesController to fetch the data and formats the response for the MCP.
*
* @param {ListProjectLanguagesToolArgsType} args - Arguments provided to the tool.
* @returns {Promise<{ content: Array<{ type: 'text', text: string }> }>} Formatted response for the MCP.
* @throws {McpError} Formatted error if the controller or service layer encounters an issue.
*/
async function handleListProjectLanguages(args) {
const methodLogger = Logger.forContext("tools/languages.tool.ts", "handleListProjectLanguages");
methodLogger.debug(`Getting Lokalise project languages for project ${args.projectId}...`, args);
try {
// Pass args directly to the controller
const result = await languagesController.listProjectLanguages(args);
methodLogger.debug("Got the response from the controller", result);
// Format the response for the MCP tool
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error(`Error getting languages for project: ${args.projectId}`, error);
return formatErrorForMcpTool(error);
}
}
/**
* @function handleAddProjectLanguages
* @description MCP Tool handler to add languages to a Lokalise project.
*
* @param {AddProjectLanguagesToolArgsType} args - Arguments provided to the tool.
* @returns {Promise<{ content: Array<{ type: 'text', text: string }> }>} Formatted response for the MCP.
* @throws {McpError} Formatted error if the controller or service layer encounters an issue.
*/
async function handleAddProjectLanguages(args) {
const methodLogger = Logger.forContext("tools/languages.tool.ts", "handleAddProjectLanguages");
methodLogger.debug(`Adding ${args.languages.length} languages to project ${args.projectId}...`, { projectId: args.projectId, languageCount: args.languages.length });
try {
const result = await languagesController.addProjectLanguages(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error(`Error adding languages to project: ${args.projectId}`, error);
return formatErrorForMcpTool(error);
}
}
/**
* @function handleGetLanguage
* @description MCP Tool handler to get detailed information about a specific language.
*
* @param {GetLanguageToolArgsType} args - Arguments provided to the tool.
* @returns {Promise<{ content: Array<{ type: 'text', text: string }> }>} Formatted response for the MCP.
* @throws {McpError} Formatted error if the controller or service layer encounters an issue.
*/
async function handleGetLanguage(args) {
const methodLogger = Logger.forContext("tools/languages.tool.ts", "handleGetLanguage");
methodLogger.debug(`Getting language ${args.languageId} from project ${args.projectId}...`, args);
try {
const result = await languagesController.getLanguage(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error(`Error getting language ${args.languageId} from project: ${args.projectId}`, error);
return formatErrorForMcpTool(error);
}
}
/**
* @function handleUpdateLanguage
* @description MCP Tool handler to update an existing language.
*
* @param {UpdateLanguageToolArgsType} args - Arguments provided to the tool.
* @returns {Promise<{ content: Array<{ type: 'text', text: string }> }>} Formatted response for the MCP.
* @throws {McpError} Formatted error if the controller or service layer encounters an issue.
*/
async function handleUpdateLanguage(args) {
const methodLogger = Logger.forContext("tools/languages.tool.ts", "handleUpdateLanguage");
methodLogger.debug(`Updating language ${args.languageId} in project ${args.projectId}...`, { projectId: args.projectId, languageId: args.languageId });
try {
const result = await languagesController.updateLanguage(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error(`Error updating language ${args.languageId} in project: ${args.projectId}`, error);
return formatErrorForMcpTool(error);
}
}
/**
* @function handleRemoveLanguage
* @description MCP Tool handler to remove a language from a project.
*
* @param {RemoveLanguageToolArgsType} args - Arguments provided to the tool.
* @returns {Promise<{ content: Array<{ type: 'text', text: string }> }>} Formatted response for the MCP.
* @throws {McpError} Formatted error if the controller or service layer encounters an issue.
*/
async function handleRemoveLanguage(args) {
const methodLogger = Logger.forContext("tools/languages.tool.ts", "handleRemoveLanguage");
methodLogger.debug(`Removing language ${args.languageId} from project ${args.projectId}...`, { projectId: args.projectId, languageId: args.languageId });
try {
const result = await languagesController.removeLanguage(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error(`Error removing language ${args.languageId} from project: ${args.projectId}`, error);
return formatErrorForMcpTool(error);
}
}
/**
* @function registerTools
* @description Registers all Languages tools with the MCP server.
*
* @param {McpServer} server - The MCP server instance.
*/
function registerTools(server) {
const methodLogger = Logger.forContext("tools/languages.tool.ts", "registerTools");
methodLogger.debug("Registering Languages tools...");
// Register system languages listing tool
server.tool("lokalise_list_system_languages", "Discovers all languages available in Lokalise platform that can be added to projects. Optional: limit (100), page. Use to find supported languages before project setup, verify language codes, or check RTL/plural form support. Returns: Languages with ISO codes, native names, RTL status, plural forms. Essential before adding new target languages.", ListSystemLanguagesToolArgs.shape, handleListSystemLanguages);
// Register project languages listing tool
server.tool("lokalise_list_project_languages", "Shows which languages are currently being translated in a project. Required: projectId. Optional: includeProgress (shows completion %), limit, page. Use to audit translation coverage, identify incomplete languages, or prepare reports. Returns: Active languages with progress stats. Start here to understand project's localization scope.", ListProjectLanguagesToolArgs.shape, handleListProjectLanguages);
// Register add project languages tool
server.tool("lokalise_add_project_languages", "Starts translating into new languages by adding them to the project. Required: projectId, languages array with {lang_iso}. Optional per language: custom_iso, custom_name, custom_plural_forms. Use when expanding to new markets or adding regional variants. Returns: Added languages with IDs. Tip: Check system languages first for valid ISO codes.", AddProjectLanguagesToolArgs.shape, handleAddProjectLanguages);
// Register get language tool
server.tool("lokalise_get_language", "Examines detailed settings for a specific project language. Required: projectId, languageId. Use to verify plural rules, check RTL configuration, or understand custom settings. Returns: Complete language configuration including ISO codes, plural forms, and writing direction. Important for languages with complex grammar rules.", GetLanguageToolArgs.shape, handleGetLanguage);
// Register update language tool
server.tool("lokalise_update_language", "Modifies language settings within a project. Required: projectId, languageId, languageData object. Optional in data: lang_iso, lang_name, plural_forms. Use to fix incorrect configurations, customize language names, or adjust plural rules. Returns: Updated language settings. Changes affect how translations are handled.", UpdateLanguageToolArgs.shape, handleUpdateLanguage);
// Register remove language tool
server.tool("lokalise_remove_language", "Drops support for a language by removing it from the project. Required: projectId, languageId. Use when discontinuing localization for a market or cleaning up test languages. Returns: Removal confirmation. Critical Warning: Permanently deletes ALL translations for this language. Export translations first if needed.", RemoveLanguageToolArgs.shape, handleRemoveLanguage);
methodLogger.debug("Successfully registered all Languages tools.");
}
const languagesTools = {
registerTools,
getMeta() {
return {
name: "languages",
description: "Languages management domain",
version: "1.0.0",
toolsCount: 6,
};
},
};
export default languagesTools;