lokalise-mcp
Version:
The Lokalise MCP Server brings Lokalise's localization power to Claude and AI assistants—manage projects, keys, and translations by chat.
260 lines (259 loc) • 12.8 kB
JavaScript
import { formatErrorForMcpTool } from "../../shared/utils/error.util.js";
import { Logger } from "../../shared/utils/logger.util.js";
import keysController from "./keys.controller.js";
import { BulkDeleteKeysToolArgs, BulkUpdateKeysToolArgs, CreateKeysToolArgs, DeleteKeyToolArgs, GetKeyToolArgs, ListKeysToolArgs, UpdateKeyToolArgs, } from "./keys.types.js";
/**
* @function handleListKeys
* @description MCP Tool handler to retrieve a list of keys from a Lokalise project.
* It calls the keysController to fetch the data and formats the response for the MCP.
*
* @param {ListKeysToolArgsType} 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 handleListKeys(args) {
const methodLogger = Logger.forContext("tools/keys.tool.ts", "handleListKeys");
methodLogger.debug(`Getting Lokalise keys list (limit: ${args.limit || "default"}, page: ${args.page || "1"})...`, args);
try {
// Pass args directly to the controller
const result = await keysController.listKeys(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 in handleListKeys", { error, args });
throw formatErrorForMcpTool({
error,
message: "Failed to list keys",
});
}
}
/**
* @function handleCreateKeys
* @description MCP Tool handler to create multiple keys in a Lokalise project.
*
* @param {CreateKeysToolArgsType} 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 handleCreateKeys(args) {
const methodLogger = Logger.forContext("tools/keys.tool.ts", "handleCreateKeys");
methodLogger.debug(`Creating ${args.keys.length} keys in project ${args.projectId}...`, args);
try {
const result = await keysController.createKeys(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error("Error in handleCreateKeys", { error, args });
throw formatErrorForMcpTool({
error,
message: "Failed to create keys",
});
}
}
/**
* @function handleGetKey
* @description MCP Tool handler to retrieve a single key from a Lokalise project.
*
* @param {GetKeyToolArgsType} 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 handleGetKey(args) {
const methodLogger = Logger.forContext("tools/keys.tool.ts", "handleGetKey");
methodLogger.debug(`Getting key ${args.keyId} from project ${args.projectId}...`, args);
try {
const result = await keysController.getKey(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error("Error in handleGetKey", { error, args });
throw formatErrorForMcpTool({
error,
message: "Failed to get key",
});
}
}
/**
* @function handleUpdateKey
* @description MCP Tool handler to update a single key in a Lokalise project.
*
* @param {UpdateKeyToolArgsType} 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 handleUpdateKey(args) {
const methodLogger = Logger.forContext("tools/keys.tool.ts", "handleUpdateKey");
methodLogger.debug(`Updating key ${args.keyId} in project ${args.projectId}...`, args);
try {
const result = await keysController.updateKey(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error("Error in handleUpdateKey", { error, args });
throw formatErrorForMcpTool({
error,
message: "Failed to update key",
});
}
}
/**
* @function handleDeleteKey
* @description MCP Tool handler to delete a single key from a Lokalise project.
*
* @param {DeleteKeyToolArgsType} 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 handleDeleteKey(args) {
const methodLogger = Logger.forContext("tools/keys.tool.ts", "handleDeleteKey");
methodLogger.debug(`Deleting key ${args.keyId} from project ${args.projectId}...`, args);
try {
const result = await keysController.deleteKey(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error("Error in handleDeleteKey", { error, args });
throw formatErrorForMcpTool({
error,
message: "Failed to delete key",
});
}
}
/**
* @function handleBulkUpdateKeys
* @description MCP Tool handler to update multiple keys in a Lokalise project.
*
* @param {BulkUpdateKeysToolArgsType} 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 handleBulkUpdateKeys(args) {
const methodLogger = Logger.forContext("tools/keys.tool.ts", "handleBulkUpdateKeys");
methodLogger.debug(`Bulk updating ${args.keys.length} keys in project ${args.projectId}...`, args);
try {
const result = await keysController.bulkUpdateKeys(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error("Error in handleBulkUpdateKeys", { error, args });
throw formatErrorForMcpTool({
error,
message: "Failed to bulk update keys",
});
}
}
/**
* @function handleBulkDeleteKeys
* @description MCP Tool handler to delete multiple keys from a Lokalise project.
*
* @param {BulkDeleteKeysToolArgsType} 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 handleBulkDeleteKeys(args) {
const methodLogger = Logger.forContext("tools/keys.tool.ts", "handleBulkDeleteKeys");
methodLogger.debug(`Bulk deleting ${args.keyIds.length} keys from project ${args.projectId}...`, args);
try {
const result = await keysController.bulkDeleteKeys(args);
methodLogger.debug("Got the response from the controller", result);
return {
content: [
{
type: "text",
text: result.content,
},
],
};
}
catch (error) {
methodLogger.error("Error in handleBulkDeleteKeys", { error, args });
throw formatErrorForMcpTool({
error,
message: "Failed to bulk delete keys",
});
}
}
/**
* Register all MCP tools for the Keys collection with the server
*/
function registerTools(server) {
const logger = Logger.forContext("tools/keys.tool.ts", "registerTools");
logger.debug("Registering Keys MCP tools...");
// List Keys Tool
server.tool("lokalise_list_keys", "Explores the project's content structure by listing translation keys. Required: projectId. Optional: limit (100), cursor, filterKeys array, filterPlatforms array, includeTranslations. Use to browse content organization, find specific keys, or audit platform coverage. Returns: Keys with metadata and optional translations. Supports cursor pagination for large projects. Start here to understand project content.", ListKeysToolArgs.shape, handleListKeys);
// Create Keys Tool
server.tool("lokalise_create_keys", "Adds new UI text or content to be translated (up to 1000 keys per request). Required: projectId, keys array with {key_name, platforms}. Optional per key: description, tags, translations. Use for new features, initial setup, or content expansion. Returns: Created keys with IDs and any errors. Tip: Include base language translations to speed up workflow. Pairs with: lokalise_list_keys to verify.", CreateKeysToolArgs.shape, handleCreateKeys);
// Get Key Tool
server.tool("lokalise_get_key", "Deep-dives into a single content item to understand its complete state. Required: projectId, keyId. Use to investigate translation status, view all language versions, check metadata, or debug issues. Returns: Full key data including all translations, platforms, tags, comments, and history. Essential for detailed analysis or before making targeted updates.", GetKeyToolArgs.shape, handleGetKey);
// Update Key Tool
server.tool("lokalise_update_key", "Modifies key metadata to improve organization and translator context. Required: projectId, keyId. Optional: key_name, description, platforms, tags. Use to clarify meaning for translators, fix platform assignments, or reorganize content. Returns: Updated key. Note: This updates metadata only - use translation tools to modify actual text. Changes apply immediately.", UpdateKeyToolArgs.shape, handleUpdateKey);
// Delete Key Tool
server.tool("lokalise_delete_key", "Permanently removes obsolete content and all its translations. Required: projectId, keyId. Use for removing deprecated features, cleaning typos in key names, or content no longer needed. Returns: Deletion confirmation. Warning: Irreversible - all translations lost. Consider archiving important content first. For multiple keys, use bulk delete.", DeleteKeyToolArgs.shape, handleDeleteKey);
// Bulk Update Keys Tool
server.tool("lokalise_bulk_update_keys", "Efficiently modifies metadata for multiple keys in one operation. Required: projectId, keys array with {key_id} plus changes. Use for large-scale reorganization, batch platform updates, or systematic tagging. Returns: Updated keys and any errors. Performance: Processes up to 1000 keys per request. More efficient than individual updates for 3+ keys.", BulkUpdateKeysToolArgs.shape, handleBulkUpdateKeys);
// Bulk Delete Keys Tool
server.tool("lokalise_bulk_delete_keys", "Large-scale cleanup removing multiple obsolete keys permanently. Required: projectId, keyIds array. Use for removing deprecated feature sets, post-refactoring cleanup, or major content pruning. Returns: Deletion results. Critical Warning: Irreversible batch operation - all selected keys and translations permanently deleted. Always verify key list before execution.", BulkDeleteKeysToolArgs.shape, handleBulkDeleteKeys);
logger.debug("All Keys MCP tools registered successfully");
}
// Export the tools registry
const keysTools = {
registerTools,
getMeta() {
return {
name: "keys",
description: "Translation keys management domain",
version: "1.0.0",
toolsCount: 7,
};
},
};
export default keysTools;