calculate_hash
Calculate SHA-256 hash for files or directories to verify data integrity and detect changes in the local filesystem.
Instructions
Calculate SHA-256 hash of a file or directory.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Absolute path to file or directory. |
Implementation Reference
- src/tools/calculate-hash.ts:199-238 (handler)The core logic handler that determines if the path is a directory or file and computes the SHA-256 hash.
async function handleCalculateHash( args: z.infer<typeof CalculateHashInputSchema>, signal?: AbortSignal, onProgress?: (progress: { total?: number; current: number }) => void ): Promise<ToolResponse<z.infer<typeof CalculateHashOutputSchema>>> { const validPath = await validateExistingPath(args.path, signal); // Check if path is a directory or file const stats = await withAbort(fs.stat(validPath), signal); if (stats.isDirectory()) { // Hash directory: composite hash of all files const { hash, fileCount } = await hashDirectory(validPath, { ...(signal ? { signal } : {}), ...(onProgress ? { onProgress } : {}), }); return buildToolResponse(`${hash} (${fileCount} files)`, { ok: true, path: validPath, hash, isDirectory: true, fileCount, }); } else { // Hash single file const hash = await hashFile(validPath, 'hex', signal); reportPeriodicProgress(onProgress, 1, { throttleModulo: 25, force: true, }); return buildToolResponse(hash, { ok: true, path: validPath, hash, isDirectory: false, }); } } - src/tools/calculate-hash.ts:240-328 (registration)Registers the 'calculate_hash' tool with the MCP server, including progress tracking and input/output validation.
export function registerCalculateHashTool( server: McpServer, options: ToolRegistrationOptions = {} ): void { const handler = ( args: z.infer<typeof CalculateHashInputSchema>, extra: ToolExtra ): Promise<ToolResult<z.infer<typeof CalculateHashOutputSchema>>> => executeToolWithDiagnostics({ toolName: 'calculate_hash', extra, outputSchema: CalculateHashOutputSchema, timedSignal: {}, context: { path: args.path }, run: async (signal) => { const baseName = path.basename(args.path); const progress = createToolProgressSession( extra, `🕮 hash: ${baseName}` ); const progressWithMessage = ({ current, total, }: { total?: number; current: number; }): void => { progress.update({ current, ...(total !== undefined ? { total } : {}), message: `🕮 hash: ${baseName} [${current} files]`, }); }; try { const result = await handleCalculateHash( args, signal, progressWithMessage ); const sc = result.structuredContent; const totalFiles = sc.fileCount ?? 1; const finalCurrent = resolveFinalProgressCurrent( progress, totalFiles + 1 ); let suffix: string; if (sc.fileCount !== undefined && sc.fileCount > 1) { suffix = `${sc.fileCount} files • ${(sc.hash ?? '').slice(0, 8)}…`; } else { suffix = `${(sc.hash ?? '').slice(0, 8)}…`; } progress.complete(`🕮 hash: ${baseName} • ${suffix}`, finalCurrent); return result; } catch (error) { progress.fail(`🕮 hash: ${baseName} • failed`); throw error; } }, onError: (error) => buildToolErrorResponse(error, ErrorCode.E_UNKNOWN, args.path), }); const wrappedHandler = wrapToolHandler(handler, { guard: options.isInitialized, }); const validatedHandler = withValidatedArgs( CalculateHashInputSchema, wrappedHandler ); if ( registerToolTaskIfAvailable( server, 'calculate_hash', CALCULATE_HASH_TOOL, validatedHandler, options.iconInfo, options.isInitialized ) ) return; server.registerTool( 'calculate_hash', withDefaultIcons({ ...CALCULATE_HASH_TOOL }, options.iconInfo), validatedHandler ); } - src/schemas.ts:743-750 (schema)Defines the input and output schemas for the 'calculate_hash' tool.
export const CalculateHashInputSchema = z.strictObject({ path: RequiredPathSchema.describe(DESC_PATH_REQUIRED), }); export const CalculateHashOutputSchema = z.strictObject({ ok: SuccessFlagSchema, path: z.string().optional(), hash: Sha256HexSchema.optional().describe('SHA-256 hash'),