Skip to content

Implement translate-document tool for translating documents via the DeepL API #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 69 additions & 3 deletions src/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import * as deepl from 'deepl-node';
import { join, basename, extname } from 'path';
import { tmpdir } from 'os';

const DEEPL_API_KEY = process.env.DEEPL_API_KEY;
const deeplClient = new deepl.DeepLClient(DEEPL_API_KEY);
Expand All @@ -30,15 +32,23 @@ async function getTargetLanguages() {
return targetLanguagesCache;
}

// Helper function to validate languages
async function validateLanguages(targetLang) {
// Helper function to validate target languages
async function validateTargetLanguage(targetLang) {
const targetLanguages = await getTargetLanguages();

if (!targetLanguages.some(lang => lang.code === targetLang)) {
throw new Error(`Invalid target language: ${targetLang}. Available languages: ${targetLanguages.map(l => l.code).join(', ')}`);
}
}

// Helper function to validate source languages
async function validateSourceLanguage(sourceLang) {
const sourceLanguages = await getSourceLanguages();

if (!sourceLanguages.some(lang => lang.code === sourceLang)) {
throw new Error(`Invalid source language: ${sourceLang}. Available languages: ${sourceLanguages.map(l => l.code).join(', ')}`);
}
}

// Create server instance
const server = new McpServer({
Expand Down Expand Up @@ -109,7 +119,7 @@ server.tool(
},
async ({ text, targetLang, formality }) => {
// Validate languages before translation
await validateLanguages(targetLang);
await validateTargetLanguage(targetLang);

try {
const result = await deeplClient.translateText(
Expand Down Expand Up @@ -193,6 +203,62 @@ server.tool(
}
);

server.tool(
"translate-document",
"Translate a document (file) from one language to another using DeepL API",
{
inputFile: z.string().describe("Path to the input file to be translated"),
sourceLang: z.string().optional().describe("Language code of the input file (if omitted, DeepL will auto-detect)"),
targetLang: z.string().describe("Target language code (e.g. 'en-US', 'de', 'fr')"),
formality: z
.enum(["less", "more", "default", "prefer_less", "prefer_more"])
.optional()
.describe(
"Controls whether translations should lean toward informal or formal language"
),
},
async ({ inputFile, sourceLang, targetLang, formality }) => {
// Validate languages before translation
if (sourceLang) {
await validateSourceLanguage(sourceLang);
}
await validateTargetLanguage(targetLang);

const fileExtension = extname(inputFile);
const fileNameWithoutExt = basename(inputFile, fileExtension);
const tmpOutputFile = join(tmpdir(), `${fileNameWithoutExt} ${targetLang}${fileExtension}`);

try {
await deeplClient.translateDocument(
inputFile,
tmpOutputFile,
// @ts-ignore
sourceLang ?? null,
targetLang,
{ formality }
);

return {
content: [
{
type: "text",
text: `Document successfully translated and saved to: ${tmpOutputFile}`,
},
],
};
} catch (error) {
if (error.documentHandle) {
const handle = error.documentHandle;
throw new Error(
`Translation failed after document upload. Document ID: ${handle.documentId}, ` +
`Document key: ${handle.documentKey}. Original error: ${error.message}`
);
}
throw new Error(`Document translation failed: ${error.message}`);
}
}
);

async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
Expand Down