diff
Diff npm packages: compare two package versions, or a local package against its published registry version. Specify versions via range or array, or provide local path.
Instructions
Show diff between package versions or between local and registry
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| package | No | Package spec for comparison (e.g. pkg@1.0.0..pkg@2.0.0) | |
| specs | No | Two package specs to compare (e.g. ['pkg@1.0.0', 'pkg@2.0.0']) | |
| path | No | Absolute path to local package (compares local vs registry) | |
| diffNameOnly | No | Only show file names that changed |
Implementation Reference
- src/index.ts:671-689 (handler)The handler function for the 'diff' tool. It constructs npm diff CLI arguments (--diff for package specs, --diff-name-only option), executes the npm diff command via the run() helper, and returns the stdout as text content or an error message.
async ({ package: pkg, specs, path, diffNameOnly }) => { const args = ["diff"]; if (specs && specs.length > 0) { for (const s of specs) args.push(`--diff=${s}`); } else if (pkg) { args.push(`--diff=${pkg}`); } if (diffNameOnly) args.push("--diff-name-only"); try { const { stdout } = await run(args, path); return { content: [{ type: "text", text: stdout || "No differences found" }] }; } catch (e: any) { return { content: [{ type: "text", text: `Error: ${e.stderr || e.message}` }], isError: true, }; } }, ); - src/index.ts:662-670 (schema)Schema/registration for the 'diff' tool showing its name, description, and input parameters defined with Zod (package, specs, path, diffNameOnly).
server.tool( "diff", "Show diff between package versions or between local and registry", { package: z.string().optional().describe("Package spec for comparison (e.g. pkg@1.0.0..pkg@2.0.0)"), specs: z.array(z.string()).optional().describe("Two package specs to compare (e.g. ['pkg@1.0.0', 'pkg@2.0.0'])"), path: z.string().optional().describe("Absolute path to local package (compares local vs registry)"), diffNameOnly: z.boolean().optional().describe("Only show file names that changed"), }, - src/index.ts:661-689 (registration)Full registration of the 'diff' tool on the MCP server with server.tool(). Includes schema, description, and handler.
// ── npm diff ── server.tool( "diff", "Show diff between package versions or between local and registry", { package: z.string().optional().describe("Package spec for comparison (e.g. pkg@1.0.0..pkg@2.0.0)"), specs: z.array(z.string()).optional().describe("Two package specs to compare (e.g. ['pkg@1.0.0', 'pkg@2.0.0'])"), path: z.string().optional().describe("Absolute path to local package (compares local vs registry)"), diffNameOnly: z.boolean().optional().describe("Only show file names that changed"), }, async ({ package: pkg, specs, path, diffNameOnly }) => { const args = ["diff"]; if (specs && specs.length > 0) { for (const s of specs) args.push(`--diff=${s}`); } else if (pkg) { args.push(`--diff=${pkg}`); } if (diffNameOnly) args.push("--diff-name-only"); try { const { stdout } = await run(args, path); return { content: [{ type: "text", text: stdout || "No differences found" }] }; } catch (e: any) { return { content: [{ type: "text", text: `Error: ${e.stderr || e.message}` }], isError: true, }; } }, ); - src/index.ts:26-38 (helper)Helper function 'run' that executes npm commands using promisified execFile. Used by the diff handler to run 'npm diff'.
async function run( args: string[], cwd?: string, ): Promise<{ stdout: string; stderr: string }> { const fullArgs = [...args, ...npmrcArgs]; const opts: { cwd?: string; timeout: number; env: NodeJS.ProcessEnv; maxBuffer: number } = { timeout: 120_000, maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large outputs env: { ...process.env, NO_COLOR: "1" }, }; if (cwd) opts.cwd = cwd; return exec(NPM, fullArgs, opts); } - src/index.ts:1337-1342 (registration)Sandbox registration of the 'diff' tool with a noop handler (used in sandbox/smithery mode).
sandbox.tool("diff", "Show diff between package versions", { package: z.string().optional().describe("Package spec for comparison"), specs: z.array(z.string()).optional().describe("Two package specs to compare"), path: z.string().optional().describe("Absolute path to local package"), diffNameOnly: z.boolean().optional().describe("Only show file names that changed"), }, noop);