diff --git a/.gitignore b/.gitignore index fca9b9f..ca9d4b3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ node_modules/ # Build output dist +dxt_build +dxt_output # Temporary files tests/assets/test-output-* diff --git a/bin/build_dxt b/bin/build_dxt new file mode 100755 index 0000000..292c885 --- /dev/null +++ b/bin/build_dxt @@ -0,0 +1,65 @@ +#!/usr/bin/env bash + +set -euo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" + +if [ $? -ne 0 ]; then + echo "Error: Not in a git repository" + exit 1 +fi + +CURRENT_DIR="$(pwd)" + +if [ "$CURRENT_DIR" != "$REPO_ROOT" ]; then + echo "Error: This script must be run from the repository root" + echo "Current directory: $CURRENT_DIR" + echo "Repository root: $REPO_ROOT" + echo "Please cd to the repository root and run again" + exit 1 +fi + +APP_VERSION=$(node -e 'console.log(require("./package.json").version)') +COMMIT_SHA=$(git rev-parse --short HEAD) +OUTPUT_FILENAME="nutrient-dws-mcp-server@$APP_VERSION-$COMMIT_SHA.dxt" + +echo "Building $OUTPUT_FILENAME" +echo "Git revision: $COMMIT_SHA" + +pnpm run clean && pnpm run build +mkdir -p dxt_build +mkdir -p dxt_output +cp -a dist dxt_build/dist + +# Copy required files from package.json "files" field +cp README.md dxt_build/README.md +cp LICENSE dxt_build/LICENSE +cp -a resources dxt_build/resources + +# Copy manifest.json with version substitution +sed -e "s/{{APP_VERSION_PLACEHOLDER}}/$APP_VERSION/" manifest.json > dxt_build/manifest.json + +# Copy package.json for npm ci +cp package.json dxt_build/package.json + +# Generate package-lock.json for npm ci +cd dxt_build && npm install --package-lock-only --omit=dev && cd "$REPO_ROOT" + +cd dxt_build/ + +echo "Installing production dependencies in dxt_build/" +npm ci --omit=dev + +echo "Unpacked extension is in: dxt_build/" + +cd "$REPO_ROOT" + +cd dxt_build && pnpm exec dxt pack +cd "$REPO_ROOT" +mv dxt_build/dxt_build.dxt "dxt_output/$OUTPUT_FILENAME" + +echo "DXT package created: dxt_output/$OUTPUT_FILENAME" + +echo "Signing DXT package..." +pnpm exec dxt sign "dxt_output/$OUTPUT_FILENAME" --self-signed +echo "Signed DXT package: dxt_output/$OUTPUT_FILENAME" diff --git a/eslint.config.mjs b/eslint.config.mjs index b51022c..e095679 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,7 +5,7 @@ export default tseslint.config( eslint.configs.recommended, tseslint.configs.recommended, { - ignores: ['./dist/**'], + ignores: ['./dist/**', './dxt_build/**', './dxt_output/**'], }, { rules: { diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..124cd2b --- /dev/null +++ b/manifest.json @@ -0,0 +1,98 @@ +{ + "dxt_version": "0.1", + "name": "@nutrient-sdk/dws-mcp-server", + "display_name": "Nutrient DWS MCP Server", + "version": "{{APP_VERSION_PLACEHOLDER}}", + "description": "Powerful PDF processing capabilities via the Nutrient Document Web Service API including digital signing, OCR, format conversion, and document manipulation.", + "long_description": "Integrates with the Nutrient Document Web Service (DWS) Processor API to provide comprehensive PDF processing capabilities.\n\nFeatures include: document creation by merging PDFs/Office docs/images, digital signing with PAdES standards-compliant signatures, format conversion (PDF⇄DOCX/images/PDF/A), advanced OCR with multi-language support, watermarking and redaction, data extraction from text and tables, security operations like password protection, and file optimization. \n\nOperates in a secure sandbox mode to restrict file operations to a specified directory, making it ideal for document workflows.", + "author": { + "name": "Nutrient", + "url": "https://www.nutrient.io", + "email": "support@nutrient.io" + }, + "homepage": "https://www.nutrient.io/api", + "documentation": "https://github.com/PSPDFKit/nutrient-dws-mcp-server", + "support": "https://github.com/PSPDFKit/nutrient-dws-mcp-server/issues", + "icon": "resources/nutrient-logo.png", + "screenshots": [ + "resources/readme-header.png" + ], + "server": { + "type": "node", + "entry_point": "dist/index.js", + "mcp_config": { + "command": "node", + "args": [ + "${__dirname}/dist/index.js" + ], + "env": { + "NUTRIENT_DWS_API_KEY": "${user_config.NUTRIENT_DWS_API_KEY}", + "SANDBOX_PATH": "${user_config.SANDBOX_PATH}" + } + } + }, + "tools": [ + { + "name": "document_processor", + "description": "Document creation, editing, format conversion, data extraction, security, OCR, and optimization. Merge PDFs/Office docs/images, watermark, rotate, flatten, redact, convert PDF↔DOCX/images/PDF/A, extract text/tables/content, password protection, multi-language OCR, and file compression." + }, + { + "name": "document_signer", + "description": "Digital signing with PAdES standards-compliant signatures using trusted certificates. Supports CMS/PKCS#7 and CAdES signature types with customizable appearance, positioning, watermarks and graphics." + }, + { + "name": "directory_tree", + "description": "Returns the directory tree of a given path. All paths are resolved relative to root directory. Only available when sandbox mode is disabled." + }, + { + "name": "sandbox_file_tree", + "description": "Returns the file tree of the sandbox directory when sandbox mode is enabled. Recurses into subdirectories and returns a list of files and directories." + } + ], + "compatibility": { + "platforms": [ + "darwin", + "win32", + "linux" + ], + "runtimes": { + "node": ">=18.0.0" + } + }, + "user_config": { + "NUTRIENT_DWS_API_KEY": { + "type": "string", + "title": "Nutrient Document Web Service API Key", + "description": "Your API key for accessing Nutrient Document Web Service. Get your free API key at: https://dashboard.nutrient.io/sign_up/", + "required": true, + "sensitive": true + }, + "SANDBOX_PATH": { + "type": "directory", + "title": "Document Processing Sandbox Directory", + "description": "Choose a directory to contain all document processing operations. This sandbox restricts file access to only this directory and its subdirectories for security. Place your input documents here and processed outputs will be saved here. Highly recommended for safe document workflows.", + "required": true, + "sensitive": false, + "default": "${HOME}" + } + }, + "keywords": [ + "mcp", + "nutrient", + "dws", + "document", + "pdf", + "extract", + "convert", + "sign", + "watermark", + "annotation", + "form", + "edit" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/PSPDFKit/nutrient-dws-mcp-server.git" + } +} diff --git a/package.json b/package.json index 6af933c..17b32d3 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "files": [ "dist", "README.md", - "LICENSE" + "LICENSE", + "resources" ], "scripts": { "build": "tsc && shx chmod +x dist/index.js", @@ -35,15 +36,17 @@ "pretest": "tsc --project tsconfig.test.json --noEmit", "test": "vitest run", "test:watch": "vitest", - "clean": "shx rm -rf dist" + "clean": "shx rm -rf dist dxt_build dxt_output", + "pack:dxt": "./bin/build_dxt" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.11.2", + "@modelcontextprotocol/sdk": "^1.15.1", "axios": "^1.9.0", "form-data": "^4.0.2", "zod": "^3.24.3" }, "devDependencies": { + "@anthropic-ai/dxt": "^0.2.5", "@eslint/js": "^9.26.0", "@types/node": "^22.15.2", "dotenv": "^16.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c16286..ffad2d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@modelcontextprotocol/sdk': - specifier: ^1.11.2 - version: 1.12.0 + specifier: ^1.15.1 + version: 1.15.1 axios: specifier: ^1.9.0 version: 1.9.0 @@ -21,6 +21,9 @@ importers: specifier: ^3.24.3 version: 3.25.23 devDependencies: + '@anthropic-ai/dxt': + specifier: ^0.2.5 + version: 0.2.5 '@eslint/js': specifier: ^9.26.0 version: 9.27.0 @@ -47,10 +50,14 @@ importers: version: 8.32.1(eslint@9.27.0)(typescript@5.8.3) vitest: specifier: ^3.1.2 - version: 3.1.4(@types/node@22.15.21) + version: 3.1.4(@types/node@22.15.21)(tsx@4.20.3) packages: + '@anthropic-ai/dxt@0.2.5': + resolution: {integrity: sha512-vFibMY6+8dlT0cqZIjN9TES7x/V+sQ3SUGKCgqxb1TkpXELW2IhYkNB975FKV4mrCOlc15M6QQoiKwkrJIHTRA==} + hasBin: true + '@esbuild/aix-ppc64@0.25.4': resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} engines: {node: '>=18'} @@ -259,11 +266,67 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@inquirer/checkbox@3.0.1': + resolution: {integrity: sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ==} + engines: {node: '>=18'} + + '@inquirer/confirm@4.0.1': + resolution: {integrity: sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w==} + engines: {node: '>=18'} + + '@inquirer/core@9.2.1': + resolution: {integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==} + engines: {node: '>=18'} + + '@inquirer/editor@3.0.1': + resolution: {integrity: sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q==} + engines: {node: '>=18'} + + '@inquirer/expand@3.0.1': + resolution: {integrity: sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ==} + engines: {node: '>=18'} + + '@inquirer/figures@1.0.12': + resolution: {integrity: sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==} + engines: {node: '>=18'} + + '@inquirer/input@3.0.1': + resolution: {integrity: sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg==} + engines: {node: '>=18'} + + '@inquirer/number@2.0.1': + resolution: {integrity: sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ==} + engines: {node: '>=18'} + + '@inquirer/password@3.0.1': + resolution: {integrity: sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ==} + engines: {node: '>=18'} + + '@inquirer/prompts@6.0.1': + resolution: {integrity: sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==} + engines: {node: '>=18'} + + '@inquirer/rawlist@3.0.1': + resolution: {integrity: sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ==} + engines: {node: '>=18'} + + '@inquirer/search@2.0.1': + resolution: {integrity: sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg==} + engines: {node: '>=18'} + + '@inquirer/select@3.0.1': + resolution: {integrity: sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q==} + engines: {node: '>=18'} + + '@inquirer/type@2.0.0': + resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} + engines: {node: '>=18'} + '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - '@modelcontextprotocol/sdk@1.12.0': - resolution: {integrity: sha512-m//7RlINx1F3sz3KqwY1WWzVgTcYX52HYk4bJ1hkBXV3zccAEth+jRvG8DBRrdaQuRsPAJOx2MH3zaHNCKL7Zg==} + '@modelcontextprotocol/sdk@1.15.1': + resolution: {integrity: sha512-W/XlN9c528yYn+9MQkVjxiTPgPxoxt+oczfjHBDsJx0+59+O7B75Zhsp0B16Xbwbz8ANISDajh6+V7nIcPMc5w==} engines: {node: '>=18'} '@nodelib/fs.scandir@2.1.5': @@ -384,9 +447,15 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/mute-stream@0.0.4': + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + '@types/node@22.15.21': resolution: {integrity: sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==} + '@types/wrap-ansi@3.0.0': + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + '@typescript-eslint/eslint-plugin@8.32.1': resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -480,6 +549,14 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -542,10 +619,17 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -557,6 +641,10 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -623,6 +711,9 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -736,6 +827,10 @@ packages: resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} engines: {node: '>= 18'} + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -760,6 +855,9 @@ packages: picomatch: optional: true + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -783,6 +881,10 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + flora-colossus@2.0.0: + resolution: {integrity: sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA==} + engines: {node: '>= 12'} + follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -804,6 +906,10 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -812,6 +918,10 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + galactus@1.0.0: + resolution: {integrity: sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ==} + engines: {node: '>= 12'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -824,6 +934,9 @@ packages: resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} engines: {node: '>=6'} + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -840,6 +953,9 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -863,6 +979,10 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -875,6 +995,10 @@ packages: resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==} engines: {node: '>= 4'} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -902,6 +1026,10 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -933,6 +1061,9 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1002,6 +1133,10 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1017,6 +1152,10 @@ packages: nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} @@ -1040,6 +1179,10 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} @@ -1114,6 +1257,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -1151,6 +1298,9 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -1246,6 +1396,10 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -1260,6 +1414,14 @@ packages: std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + strip-eof@1.0.0: resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} engines: {node: '>=0.10.0'} @@ -1298,6 +1460,10 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1312,10 +1478,19 @@ packages: peerDependencies: typescript: '>=4.8.4' + tsx@4.20.3: + resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + type-is@2.0.1: resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} engines: {node: '>= 0.6'} @@ -1335,6 +1510,10 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -1437,6 +1616,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -1444,6 +1627,10 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yoctocolors-cjs@2.1.2: + resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} + engines: {node: '>=18'} + zod-to-json-schema@3.24.5: resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} peerDependencies: @@ -1452,8 +1639,24 @@ packages: zod@3.25.23: resolution: {integrity: sha512-Od2bdMosahjSrSgJtakrwjMDb1zM1A3VIHCPGveZt/3/wlrTWBya2lmEh2OYe4OIu8mPTmmr0gnLHIWQXdtWBg==} + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + snapshots: + '@anthropic-ai/dxt@0.2.5': + dependencies: + '@inquirer/prompts': 6.0.1 + commander: 13.1.0 + fflate: 0.8.2 + galactus: 1.0.0 + ignore: 7.0.5 + node-forge: 1.3.1 + pretty-bytes: 5.6.0 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + '@esbuild/aix-ppc64@0.25.4': optional: true @@ -1586,15 +1789,112 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@inquirer/checkbox@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.12 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + + '@inquirer/confirm@4.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/core@9.2.1': + dependencies: + '@inquirer/figures': 1.0.12 + '@inquirer/type': 2.0.0 + '@types/mute-stream': 0.0.4 + '@types/node': 22.15.21 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + + '@inquirer/editor@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + external-editor: 3.1.0 + + '@inquirer/expand@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.2 + + '@inquirer/figures@1.0.12': {} + + '@inquirer/input@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/number@2.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + + '@inquirer/password@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + + '@inquirer/prompts@6.0.1': + dependencies: + '@inquirer/checkbox': 3.0.1 + '@inquirer/confirm': 4.0.1 + '@inquirer/editor': 3.0.1 + '@inquirer/expand': 3.0.1 + '@inquirer/input': 3.0.1 + '@inquirer/number': 2.0.1 + '@inquirer/password': 3.0.1 + '@inquirer/rawlist': 3.0.1 + '@inquirer/search': 2.0.1 + '@inquirer/select': 3.0.1 + + '@inquirer/rawlist@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.2 + + '@inquirer/search@2.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.12 + '@inquirer/type': 2.0.0 + yoctocolors-cjs: 2.1.2 + + '@inquirer/select@3.0.1': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.12 + '@inquirer/type': 2.0.0 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + + '@inquirer/type@2.0.0': + dependencies: + mute-stream: 1.0.0 + '@jridgewell/sourcemap-codec@1.5.0': {} - '@modelcontextprotocol/sdk@1.12.0': + '@modelcontextprotocol/sdk@1.15.1': dependencies: ajv: 6.12.6 content-type: 1.0.5 cors: 2.8.5 cross-spawn: 7.0.6 eventsource: 3.0.7 + eventsource-parser: 3.0.2 express: 5.1.0 express-rate-limit: 7.5.0(express@5.1.0) pkce-challenge: 5.0.0 @@ -1680,10 +1980,16 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/mute-stream@0.0.4': + dependencies: + '@types/node': 22.15.21 + '@types/node@22.15.21': dependencies: undici-types: 6.21.0 + '@types/wrap-ansi@3.0.0': {} + '@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0)(typescript@5.8.3))(eslint@9.27.0)(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -1768,13 +2074,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.4(vite@6.3.5(@types/node@22.15.21))': + '@vitest/mocker@3.1.4(vite@6.3.5(@types/node@22.15.21)(tsx@4.20.3))': dependencies: '@vitest/spy': 3.1.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@22.15.21) + vite: 6.3.5(@types/node@22.15.21)(tsx@4.20.3) '@vitest/pretty-format@3.1.4': dependencies: @@ -1819,6 +2125,12 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -1895,8 +2207,12 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chardet@0.7.0: {} + check-error@2.1.1: {} + cli-width@4.1.0: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -1907,6 +2223,8 @@ snapshots: dependencies: delayed-stream: 1.0.0 + commander@13.1.0: {} + concat-map@0.0.1: {} content-disposition@1.0.0: @@ -1960,6 +2278,8 @@ snapshots: ee-first@1.1.1: {} + emoji-regex@8.0.0: {} + encodeurl@2.0.0: {} end-of-stream@1.4.4: @@ -2142,6 +2462,12 @@ snapshots: transitivePeerDependencies: - supports-color + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -2164,6 +2490,8 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fflate@0.8.2: {} + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -2195,6 +2523,13 @@ snapshots: flatted@3.3.3: {} + flora-colossus@2.0.0: + dependencies: + debug: 4.4.1 + fs-extra: 10.1.0 + transitivePeerDependencies: + - supports-color + follow-redirects@1.15.9: {} form-data@4.0.2: @@ -2208,11 +2543,25 @@ snapshots: fresh@2.0.0: {} + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fsevents@2.3.3: optional: true function-bind@1.1.2: {} + galactus@1.0.0: + dependencies: + debug: 4.4.1 + flora-colossus: 2.0.0 + fs-extra: 10.1.0 + transitivePeerDependencies: + - supports-color + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -2235,6 +2584,11 @@ snapshots: dependencies: pump: 3.0.2 + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + optional: true + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2247,6 +2601,8 @@ snapshots: gopd@1.2.0: {} + graceful-fs@4.2.11: {} + graphemer@1.4.0: {} has-flag@4.0.0: {} @@ -2269,6 +2625,10 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -2277,6 +2637,8 @@ snapshots: ignore@7.0.4: {} + ignore@7.0.5: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -2296,6 +2658,8 @@ snapshots: is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -2318,6 +2682,12 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -2376,6 +2746,8 @@ snapshots: ms@2.1.3: {} + mute-stream@1.0.0: {} + nanoid@3.3.11: {} natural-compare@1.4.0: {} @@ -2384,6 +2756,8 @@ snapshots: nice-try@1.0.5: {} + node-forge@1.3.1: {} + npm-run-path@2.0.2: dependencies: path-key: 2.0.1 @@ -2409,6 +2783,8 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + os-tmpdir@1.0.2: {} + p-finally@1.0.0: {} p-limit@3.1.0: @@ -2457,6 +2833,8 @@ snapshots: prettier@3.5.3: {} + pretty-bytes@5.6.0: {} + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -2492,6 +2870,9 @@ snapshots: resolve-from@4.0.0: {} + resolve-pkg-maps@1.0.0: + optional: true + resolve@1.22.10: dependencies: is-core-module: 2.16.1 @@ -2631,6 +3012,8 @@ snapshots: signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + source-map-js@1.2.1: {} stackback@0.0.2: {} @@ -2639,6 +3022,16 @@ snapshots: std-env@3.9.0: {} + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + strip-eof@1.0.0: {} strip-json-comments@3.1.1: {} @@ -2664,6 +3057,10 @@ snapshots: tinyspy@3.0.2: {} + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -2674,10 +3071,20 @@ snapshots: dependencies: typescript: 5.8.3 + tsx@4.20.3: + dependencies: + esbuild: 0.25.4 + get-tsconfig: 4.10.1 + optionalDependencies: + fsevents: 2.3.3 + optional: true + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 + type-fest@0.21.3: {} + type-is@2.0.1: dependencies: content-type: 1.0.5 @@ -2698,6 +3105,8 @@ snapshots: undici-types@6.21.0: {} + universalify@2.0.1: {} + unpipe@1.0.0: {} uri-js@4.4.1: @@ -2706,13 +3115,13 @@ snapshots: vary@1.1.2: {} - vite-node@3.1.4(@types/node@22.15.21): + vite-node@3.1.4(@types/node@22.15.21)(tsx@4.20.3): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.15.21) + vite: 6.3.5(@types/node@22.15.21)(tsx@4.20.3) transitivePeerDependencies: - '@types/node' - jiti @@ -2727,7 +3136,7 @@ snapshots: - tsx - yaml - vite@6.3.5(@types/node@22.15.21): + vite@6.3.5(@types/node@22.15.21)(tsx@4.20.3): dependencies: esbuild: 0.25.4 fdir: 6.4.4(picomatch@4.0.2) @@ -2738,11 +3147,12 @@ snapshots: optionalDependencies: '@types/node': 22.15.21 fsevents: 2.3.3 + tsx: 4.20.3 - vitest@3.1.4(@types/node@22.15.21): + vitest@3.1.4(@types/node@22.15.21)(tsx@4.20.3): dependencies: '@vitest/expect': 3.1.4 - '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@22.15.21)) + '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@22.15.21)(tsx@4.20.3)) '@vitest/pretty-format': 3.1.4 '@vitest/runner': 3.1.4 '@vitest/snapshot': 3.1.4 @@ -2759,8 +3169,8 @@ snapshots: tinyglobby: 0.2.13 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@22.15.21) - vite-node: 3.1.4(@types/node@22.15.21) + vite: 6.3.5(@types/node@22.15.21)(tsx@4.20.3) + vite-node: 3.1.4(@types/node@22.15.21)(tsx@4.20.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.15.21 @@ -2793,12 +3203,22 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrappy@1.0.2: {} yocto-queue@0.1.0: {} + yoctocolors-cjs@2.1.2: {} + zod-to-json-schema@3.24.5(zod@3.25.23): dependencies: zod: 3.25.23 zod@3.25.23: {} + + zod@3.25.76: {} diff --git a/resources/nutrient-logo.png b/resources/nutrient-logo.png new file mode 100644 index 0000000..19f67a0 Binary files /dev/null and b/resources/nutrient-logo.png differ diff --git a/src/index.ts b/src/index.ts index bca9ca4..5aa4309 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,14 +8,10 @@ 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' +import { toolDefinitions } from './tool-definitions.js' const server = new McpServer( { @@ -30,71 +26,21 @@ const server = new McpServer( }, ) -function addToolsToServer(server: McpServer, sandboxEnabled: boolean = false) { - server.tool( - 'document_processor', - `Processes documents using Nutrient DWS Processor API. Reads from and writes to file system or sandbox (if enabled). +export function addToolsToServer(server: McpServer, sandboxEnabled: boolean = false) { + // Add primary tools + const documentProcessor = toolDefinitions.find(t => t.name === 'document_processor')! + server.tool(documentProcessor.name, documentProcessor.mcpDescription, documentProcessor.schema, documentProcessor.handler) -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)}`) - } - }, - ) + const documentSigner = toolDefinitions.find(t => t.name === 'document_signer')! + server.tool(documentSigner.name, documentSigner.mcpDescription, documentSigner.schema, documentSigner.handler) + // Add directory tools based on sandbox mode 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('.'), - ) + const sandboxFileTool = toolDefinitions.find(t => t.name === 'sandbox_file_tree')! + server.tool(sandboxFileTool.name, sandboxFileTool.mcpDescription, sandboxFileTool.schema, sandboxFileTool.handler) } 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), - ) + const directoryTool = toolDefinitions.find(t => t.name === 'directory_tree')! + server.tool(directoryTool.name, directoryTool.mcpDescription, directoryTool.schema, directoryTool.handler) } } @@ -114,6 +60,7 @@ async function parseCommandLineArgs() { } export async function runServer() { + console.error('test') const { sandboxDir } = await parseCommandLineArgs() if (sandboxDir) { diff --git a/src/tool-definitions.ts b/src/tool-definitions.ts new file mode 100644 index 0000000..e90b840 --- /dev/null +++ b/src/tool-definitions.ts @@ -0,0 +1,85 @@ +/** + * Tool definitions for the MCP server + * This file contains all tool information needed for both server registration and manifest generation + */ + +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 { createErrorResponse } from './responses.js' + +export interface ToolDefinition { + name: string + mcpDescription: string + publicDescription: string + schema: any + handler: (args: any) => Promise +} + +export const toolDefinitions: ToolDefinition[] = [ + { + name: 'document_processor', + mcpDescription: `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)`, + publicDescription: 'Document creation, editing, format conversion, data extraction, security, OCR, and optimization. Merge PDFs/Office docs/images, watermark, rotate, flatten, redact, convert PDF↔DOCX/images/PDF/A, extract text/tables/content, password protection, multi-language OCR, and file compression.', + schema: BuildAPIArgsSchema.shape, + handler: async ({ instructions, outputPath }) => { + try { + return performBuildCall(instructions, outputPath) + } catch (error) { + return createErrorResponse(`Error: ${error instanceof Error ? error.message : String(error)}`) + } + } + }, + { + name: 'document_signer', + mcpDescription: `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`, + publicDescription: 'Digital signing with PAdES standards-compliant signatures using trusted certificates. Supports CMS/PKCS#7 and CAdES signature types with customizable appearance, positioning, watermarks and graphics.', + schema: SignAPIArgsSchema.shape, + handler: 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)}`) + } + } + }, + { + name: 'directory_tree', + mcpDescription: 'Returns the directory tree of a given path. All paths are resolved relative to root directory.', + publicDescription: 'Returns the directory tree of a given path. All paths are resolved relative to root directory. Only available when sandbox mode is disabled.', + schema: DirectoryTreeArgsSchema.shape, + handler: async ({ path }) => performDirectoryTreeCall(path) + }, + { + name: 'sandbox_file_tree', + mcpDescription: 'Returns the file tree of the sandbox directory. It will recurse into subdirectories and return a list of files and directories.', + publicDescription: 'Returns the file tree of the sandbox directory when sandbox mode is enabled. Recurses into subdirectories and returns a list of files and directories.', + schema: {}, + handler: async () => performDirectoryTreeCall('.') + } +]