diff --git a/CLI.md b/CLI.md index bc21b8d..904b86b 100644 --- a/CLI.md +++ b/CLI.md @@ -157,12 +157,10 @@ dxt unsign my-extension.dxt For signing extensions, you need: 1. **Certificate**: X.509 certificate in PEM format - - Should have Code Signing extended key usage - Can be self-signed (for development) or CA-issued (for production) 2. **Private Key**: Corresponding private key in PEM format - - Must match the certificate's public key 3. **Intermediate Certificates** (optional): For CA-issued certificates diff --git a/MANIFEST.md b/MANIFEST.md index d1dab68..68d27c0 100644 --- a/MANIFEST.md +++ b/MANIFEST.md @@ -290,14 +290,12 @@ The `server` object defines how to run the MCP server: ### Server Types 1. **Python**: `server.type = "python"` - - Requires `entry_point` to Python file - All dependencies must be bundled in the DXT - Can use `server/lib` for packages or `server/venv` for full virtual environment - Python runtime version specified in `compatibility.runtimes.python` 2. **Node.js**: `server.type = "node"` - - Requires `entry_point` to JavaScript file - All dependencies must be bundled in `node_modules` - Node.js runtime version specified in `compatibility.runtimes.node` diff --git a/examples/file-system-node/manifest.json b/examples/file-system-node/manifest.json index 7929542..e7d935e 100644 --- a/examples/file-system-node/manifest.json +++ b/examples/file-system-node/manifest.json @@ -71,11 +71,7 @@ ] } }, - "keywords": [ - "api", - "automation", - "productivity" - ], + "keywords": ["api", "automation", "productivity"], "license": "MIT", "compatibility": { "claude_desktop": ">=0.10.0", @@ -94,4 +90,4 @@ "default": [] } } -} \ No newline at end of file +} diff --git a/examples/file-system-node/package.json b/examples/file-system-node/package.json index f7f818a..e810564 100644 --- a/examples/file-system-node/package.json +++ b/examples/file-system-node/package.json @@ -7,4 +7,4 @@ "dependencies": { "@modelcontextprotocol/server-filesystem": "2025.1.14" } -} \ No newline at end of file +} diff --git a/examples/file-system-node/server/index.js b/examples/file-system-node/server/index.js index e7aa762..71582a7 100644 --- a/examples/file-system-node/server/index.js +++ b/examples/file-system-node/server/index.js @@ -13,20 +13,23 @@ const loadServer = async () => { try { // Save original argv const originalArgv = process.argv; - + // The filesystem server expects directories as command line arguments process.argv = [process.argv[0], process.argv[1], ...args]; - + // Dynamically import the ESM module - await import('@modelcontextprotocol/server-filesystem/dist/index.js'); - + await import("@modelcontextprotocol/server-filesystem/dist/index.js"); + // Restore original argv process.argv = originalArgv; } catch (error) { - console.error('Failed to load @modelcontextprotocol/server-filesystem:', error); + console.error( + "Failed to load @modelcontextprotocol/server-filesystem:", + error, + ); process.exit(1); } }; // Execute the async function -loadServer(); \ No newline at end of file +loadServer(); diff --git a/jest.config.js b/jest.config.js index 0a72f20..ed3a60e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -8,7 +8,7 @@ export default { "^.+\\.ts$": [ "ts-jest", { - tsConfig: 'tsconfig.test.json' + tsConfig: "tsconfig.test.json", }, ], }, diff --git a/package.json b/package.json index 7a4a4e6..1636061 100644 --- a/package.json +++ b/package.json @@ -78,5 +78,6 @@ "resolutions": { "@babel/helpers": "7.27.1", "@babel/parser": "7.27.3" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/scripts/build-dxt-schema.js b/scripts/build-dxt-schema.js index 9c4efe7..b9c0c74 100644 --- a/scripts/build-dxt-schema.js +++ b/scripts/build-dxt-schema.js @@ -4,9 +4,9 @@ import fs from "node:fs/promises"; import path from "node:path"; const schemasToWrite = { - 'dxt-manifest': DxtManifestSchema, - 'dxt-signature-info': DxtSignatureInfoSchema -} + "dxt-manifest": DxtManifestSchema, + "dxt-signature-info": DxtSignatureInfoSchema, +}; await fs.mkdir(path.join(import.meta.dirname, "../dist"), { recursive: true }); @@ -20,4 +20,3 @@ for (const key in schemasToWrite) { }, ); } - diff --git a/src/cli/unpack.ts b/src/cli/unpack.ts index 774ed6e..2c9c51c 100644 --- a/src/cli/unpack.ts +++ b/src/cli/unpack.ts @@ -1,5 +1,11 @@ import { unzipSync } from "fflate"; -import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs"; +import { + chmodSync, + existsSync, + mkdirSync, + readFileSync, + writeFileSync, +} from "fs"; import { join, resolve, sep } from "path"; import { extractSignatureBlock } from "../node/sign.js"; @@ -41,7 +47,7 @@ export async function unpackExtension({ if (isUnix) { // Parse ZIP central directory to extract file attributes const zipBuffer = originalContent; - + // Find end of central directory record let eocdOffset = -1; for (let i = zipBuffer.length - 22; i >= 0; i--) { @@ -54,21 +60,25 @@ export async function unpackExtension({ if (eocdOffset !== -1) { const centralDirOffset = zipBuffer.readUInt32LE(eocdOffset + 16); const centralDirEntries = zipBuffer.readUInt16LE(eocdOffset + 8); - + let offset = centralDirOffset; - + for (let i = 0; i < centralDirEntries; i++) { if (zipBuffer.readUInt32LE(offset) === 0x02014b50) { const externalAttrs = zipBuffer.readUInt32LE(offset + 38); const filenameLength = zipBuffer.readUInt16LE(offset + 28); - const filename = zipBuffer.toString('utf8', offset + 46, offset + 46 + filenameLength); - + const filename = zipBuffer.toString( + "utf8", + offset + 46, + offset + 46 + filenameLength, + ); + // Extract Unix permissions from external attributes (upper 16 bits) const mode = (externalAttrs >> 16) & 0o777; if (mode > 0) { fileAttributes.set(filename, mode); } - + const extraFieldLength = zipBuffer.readUInt16LE(offset + 30); const commentLength = zipBuffer.readUInt16LE(offset + 32); offset += 46 + filenameLength + extraFieldLength + commentLength; diff --git a/test/cli.test.ts b/test/cli.test.ts index ee82f91..b760484 100644 --- a/test/cli.test.ts +++ b/test/cli.test.ts @@ -204,10 +204,13 @@ describe("DXT CLI", () => { }, }), ); - + // Create an executable script const executableScript = join(tempExecDir, "run-script.sh"); - fs.writeFileSync(executableScript, "#!/bin/bash\necho 'Hello from executable'"); + fs.writeFileSync( + executableScript, + "#!/bin/bash\necho 'Hello from executable'", + ); fs.chmodSync(executableScript, 0o755); // Make it executable // Create a regular file for comparison @@ -221,25 +224,33 @@ describe("DXT CLI", () => { }); // Unpack the extension - execSync(`node ${cliPath} unpack ${execPackedFilePath} ${execUnpackedDir}`, { - encoding: "utf-8", - }); + execSync( + `node ${cliPath} unpack ${execPackedFilePath} ${execUnpackedDir}`, + { + encoding: "utf-8", + }, + ); // Check that the executable file preserved its permissions const originalStats = fs.statSync(executableScript); - const unpackedStats = fs.statSync(join(execUnpackedDir, "run-script.sh")); - + const unpackedStats = fs.statSync( + join(execUnpackedDir, "run-script.sh"), + ); + // Check that executable permissions are preserved (0o755) expect(unpackedStats.mode & 0o777).toBe(0o755); expect(originalStats.mode & 0o777).toBe(unpackedStats.mode & 0o777); // Check that regular file permissions are preserved (0o644) const originalRegularStats = fs.statSync(regularFile); - const unpackedRegularStats = fs.statSync(join(execUnpackedDir, "regular-file.txt")); - - expect(unpackedRegularStats.mode & 0o777).toBe(0o644); - expect(originalRegularStats.mode & 0o777).toBe(unpackedRegularStats.mode & 0o777); + const unpackedRegularStats = fs.statSync( + join(execUnpackedDir, "regular-file.txt"), + ); + expect(unpackedRegularStats.mode & 0o777).toBe(0o644); + expect(originalRegularStats.mode & 0o777).toBe( + unpackedRegularStats.mode & 0o777, + ); } finally { // Clean up fs.rmSync(tempExecDir, { recursive: true, force: true }); diff --git a/tsconfig.test.json b/tsconfig.test.json index 71278e4..6e6b840 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -4,7 +4,7 @@ "noEmit": true, "module": "node18", "moduleResolution": "node16", - "types": ["node", "jest"], + "types": ["node", "jest"] }, "include": ["src/**/*.ts", "test/**/*.ts"] }