UNPKG

@nutrient-sdk/dws-mcp-server

Version:

MCP server for Nutrient DWS Processor API

127 lines (121 loc) 5.02 kB
#!/usr/bin/env node /** * Nutrient DWS API MCP Server * * This server provides a Model Context Protocol (MCP) interface to the Nutrient DWS Processor API. */ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { BuildAPIArgsSchema, DirectoryTreeArgsSchema, SignAPIArgsSchema } from './schemas.js'; import { performBuildCall } from './dws/build.js'; import { performSignCall } from './dws/sign.js'; import { performDirectoryTreeCall } from './fs/directoryTree.js'; import { setSandboxDirectory } from './fs/sandbox.js'; import { createErrorResponse } from './responses.js'; import { getVersion } from './version.js'; import { parseSandboxPath } from './utils/sandbox.js'; const server = new McpServer({ name: 'nutrient-dws-mcp-server', version: getVersion(), }, { capabilities: { tools: {}, logging: {}, }, }); function addToolsToServer(server, sandboxEnabled = false) { server.tool('document_processor', `Processes documents using Nutrient DWS Processor API. Reads from and writes to file system or sandbox (if enabled). Features: • Import XFDF annotations • Flatten annotations • OCR processing • Page rotation • Watermarking (text/image) • Redaction creation and application Output formats: PDF, PDF/A, images (PNG, JPEG, WebP), JSON extraction, Office (DOCX, XLSX, PPTX)`, BuildAPIArgsSchema.shape, async ({ instructions, outputPath }) => { try { return performBuildCall(instructions, outputPath); } catch (error) { return createErrorResponse(`Error: ${error instanceof Error ? error.message : String(error)}`); } }); server.tool('document_signer', `Digitally signs PDF files using Nutrient DWS Sign API. Reads from and writes to file system or sandbox (if enabled). Signature types: • CMS/PKCS#7 (standard digital signatures) • CAdES (advanced electronic signatures) Appearance options: • Visible or invisible signatures • Multiple display modes (signature only, description only, or both) • Customizable elements (signer name, reason, location, date) • Support for watermarks and custom graphics Positioning: • Place on specific page coordinates • Use existing signature form fields`, SignAPIArgsSchema.shape, async ({ filePath, signatureOptions, watermarkImagePath, graphicImagePath, outputPath }) => { try { return performSignCall(filePath, outputPath, signatureOptions, watermarkImagePath, graphicImagePath); } catch (error) { return createErrorResponse(`Error: ${error instanceof Error ? error.message : String(error)}`); } }); if (sandboxEnabled) { server.tool('sandbox_file_tree', 'Returns the file tree of the sandbox directory. It will recurse into subdirectories and return a list of files and directories.', {}, async () => performDirectoryTreeCall('.')); } else { server.tool('directory_tree', 'Returns the directory tree of a given path. All paths are resolved relative to root directory.', DirectoryTreeArgsSchema.shape, async ({ path }) => performDirectoryTreeCall(path)); } } async function parseCommandLineArgs() { const args = process.argv.slice(2); try { const sandboxDir = parseSandboxPath(args, process.env.SANDBOX_PATH) || null; return { sandboxDir }; } catch (error) { await server.server.sendLoggingMessage({ level: 'error', data: `Error: ${error instanceof Error ? error.message : String(error)}`, }); process.exit(1); } } export async function runServer() { const { sandboxDir } = await parseCommandLineArgs(); if (sandboxDir) { try { await setSandboxDirectory(sandboxDir); } catch (error) { console.error(`Error setting sandbox directory: ${error instanceof Error ? error.message : String(error)}`); process.exit(1); } } else { console.warn('Info: No sandbox directory specified. File operations will not be restricted.\n' + 'Sandboxed mode is recommended - To enable sandboxed mode and restrict file operations, set SANDBOX_PATH environment variable'); } addToolsToServer(server, sandboxDir !== null); const transport = new StdioServerTransport(); await server.connect(transport); return server; } runServer() .then(async (server) => { server.server.getClientCapabilities(); await server.server.sendLoggingMessage({ level: 'info', data: `Nutrient DWS MCP Server ${getVersion()} running.`, }); }) .catch((error) => { console.error('Fatal error running server:', error); process.exit(1); }); process.stdin.on('close', async () => { await server.server.sendLoggingMessage({ level: 'info', data: `Nutrient DWS MCP Server ${getVersion()} closed.`, }); await server.close(); });