UNPKG

lokalise-mcp

Version:

The Lokalise MCP Server brings Lokalise's localization power to Claude and AI assistants—manage projects, keys, and translations by chat.

116 lines (115 loc) • 4.92 kB
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { formatErrorForMcpResource } from "../../shared/utils/error.util.js"; import { Logger } from "../../shared/utils/logger.util.js"; import controller from "./projects.controller.js"; const logger = Logger.forContext("projects.resource.ts"); /** * Register all MCP resources for the projects domain * @param server The MCP server instance to register resources with */ function registerResources(server) { const registerLogger = logger.forMethod("registerResources"); registerLogger.debug("Registering projects domain resources..."); // Register the projects list resource server.resource("lokalise-projects", new ResourceTemplate("lokalise://projects", { list: undefined, // No listing of resources needed }), async (uri) => { const methodLogger = logger.forMethod("projectsListResource"); try { // Extract optional parameters from the URI query string // Format: lokalise://projects?limit=10&page=1&includeStats=true methodLogger.debug("Projects list resource called", { uri: uri.toString(), }); const urlParams = new URLSearchParams(uri.search); const page = urlParams.get("page") ? Number.parseInt(urlParams.get("page") ?? "1", 10) : undefined; const limit = urlParams.get("limit") ? Number.parseInt(urlParams.get("limit") ?? "100", 10) : undefined; const includeStats = urlParams.get("includeStats") === "true"; // Call the controller to get the projects list const result = await controller.listProjects({ limit, page, includeStats, }); // Return the content as a text resource return { contents: [ { uri: uri.toString(), text: result.content, mimeType: "text/markdown", description: `Lokalise Projects List${limit ? ` (limit: ${limit})` : ""}${page ? ` (page: ${page})` : ""}`, }, ], }; } catch (error) { methodLogger.error("Projects list resource error", error); return formatErrorForMcpResource(error, uri.toString()); } }); // Register the project details resource server.resource("lokalise-project-details", new ResourceTemplate("lokalise://projects/{projectId}", { list: undefined, // No listing of resources needed }), async (uri) => { const methodLogger = logger.forMethod("projectDetailsResource"); try { // Extract the project ID from the request path // Format: lokalise://projects/{projectId}?includeLanguages=true&includeKeysSummary=true methodLogger.debug("Project details resource called", { uri: uri.toString(), }); // Get project ID from the path (after 'projects/') const pathParts = uri.pathname.split("/").filter(Boolean); const projectId = pathParts[1]; // Second part is the project ID after 'projects' if (!projectId) { throw new Error("Project ID is required in the URI path"); } const urlParams = new URLSearchParams(uri.search); const includeLanguages = urlParams.get("includeLanguages") === "true"; const includeKeysSummary = urlParams.get("includeKeysSummary") === "true"; // Call the controller to get the project details const result = await controller.getProjectDetails({ projectId, includeLanguages, includeKeysSummary, }); // Return the content as a text resource return { contents: [ { uri: uri.toString(), text: result.content, mimeType: "text/markdown", description: `Lokalise Project Details: ${projectId}`, }, ], }; } catch (error) { methodLogger.error("Project details resource error", error); return formatErrorForMcpResource(error, uri.toString()); } }); registerLogger.debug("Projects domain resources registered successfully"); } /** * Get metadata about the projects domain resources */ function getMeta() { return { name: "projects", description: "Lokalise projects domain resources", version: "1.0.0", resourcesCount: 2, }; } const projectsResource = { registerResources, getMeta, }; export default projectsResource;