Skip to main content
Glama

Claude MCP Server Integration

by mokemoke0821
integrity.ts12.1 kB
/** * ファイル整合性検証機能 * Phase 1: セキュリティ機能のファイル検証システム */ import { createHash } from 'crypto'; import { promises as fs } from 'fs'; import { basename, dirname, join } from 'path'; import { ChecksumResult, IntegrityVerification, OperationResult } from '../types/index.js'; import { canReadFile, createFailureResult, createOperationResult, ensureDirectory, fileExists, generateSafeFilePath, getFileInfo } from '../utils/file-helper.js'; import { logger } from '../utils/logger.js'; export class FileIntegrity { /** * ファイルのチェックサム生成 */ async generateFileChecksum( filePath: string, algorithm: 'md5' | 'sha1' | 'sha256' | 'sha512' = 'sha256' ): Promise<OperationResult<ChecksumResult>> { try { logger.info(`チェックサム生成を開始: ${filePath} (${algorithm})`); if (!await fileExists(filePath)) { throw new Error(`ファイルが見つかりません: ${filePath}`); } if (!await canReadFile(filePath)) { throw new Error(`ファイル読み取り権限がありません: ${filePath}`); } const fileInfo = await getFileInfo(filePath); const hash = createHash(algorithm); // ストリーミング処理で大きなファイルに対応 const stream = await fs.readFile(filePath); hash.update(stream); const checksum = hash.digest('hex'); const result: ChecksumResult = { filePath, algorithm, checksum, fileSize: fileInfo.size, timestamp: new Date() }; logger.info(`チェックサム生成完了: ${checksum}`); return createOperationResult(true, `チェックサムが正常に生成されました: ${checksum}`, result); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`チェックサム生成エラー: ${filePath}`, { error, algorithm }); return createFailureResult(`チェックサム生成に失敗しました: ${errorMessage}`, error instanceof Error ? error : new Error(errorMessage)); } } /** * ファイル整合性検証 */ async verifyFileIntegrity( filePath: string, expectedChecksum: string, algorithm: 'md5' | 'sha1' | 'sha256' | 'sha512' = 'sha256' ): Promise<OperationResult<IntegrityVerification>> { try { logger.info(`ファイル整合性検証を開始: ${filePath}`); // 現在のチェックサムを計算 const checksumResult = await this.generateFileChecksum(filePath, algorithm); if (!checksumResult.success || !checksumResult.data) { throw new Error(`チェックサム計算に失敗しました: ${checksumResult.message}`); } const actualChecksum = checksumResult.data.checksum; const isValid = actualChecksum.toLowerCase() === expectedChecksum.toLowerCase(); const result: IntegrityVerification = { filePath, expectedChecksum: expectedChecksum.toLowerCase(), actualChecksum: actualChecksum.toLowerCase(), algorithm, isValid, timestamp: new Date() }; const message = isValid ? `ファイル整合性検証が成功しました: チェックサムが一致します` : `ファイル整合性検証が失敗しました: チェックサムが一致しません`; logger.info(`ファイル整合性検証完了: ${isValid ? '成功' : '失敗'}`); return createOperationResult(isValid, message, result); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`ファイル整合性検証エラー: ${filePath}`, { error, algorithm }); return createFailureResult(`整合性検証に失敗しました: ${errorMessage}`, error instanceof Error ? error : new Error(errorMessage)); } } /** * 複数ファイルの一括チェックサム生成 */ async generateMultipleChecksums( filePaths: string[], algorithm: 'md5' | 'sha1' | 'sha256' | 'sha512' = 'sha256' ): Promise<OperationResult<ChecksumResult[]>> { try { logger.info(`一括チェックサム生成を開始: ${filePaths.length}ファイル`); const results: ChecksumResult[] = []; const errors: string[] = []; for (const filePath of filePaths) { const result = await this.generateFileChecksum(filePath, algorithm); if (result.success && result.data) { results.push(result.data); } else { errors.push(`${filePath}: ${result.message}`); } } if (errors.length > 0) { logger.warn(`一括チェックサム生成で一部エラー発生`, { errors }); return createOperationResult( false, `${results.length}/${filePaths.length}ファイルのチェックサム生成に成功。エラー: ${errors.join(', ')}`, results ); } logger.info(`一括チェックサム生成完了: ${results.length}ファイル`); return createOperationResult(true, `${results.length}ファイルのチェックサム生成が完了しました`, results); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`一括チェックサム生成エラー`, { error }); return createFailureResult(`一括チェックサム生成に失敗しました: ${errorMessage}`, error instanceof Error ? error : new Error(errorMessage)); } } /** * チェックサムファイルの保存 */ async saveChecksumFile( checksumResults: ChecksumResult[], outputPath?: string ): Promise<OperationResult<string>> { try { logger.info(`チェックサムファイル保存を開始: ${checksumResults.length}エントリ`); if (checksumResults.length === 0) { throw new Error('保存するチェックサム結果がありません'); } // デフォルトの出力パス生成 const finalOutputPath = outputPath || await generateSafeFilePath( join(process.cwd(), `checksums_${Date.now()}.txt`) ); await ensureDirectory(dirname(finalOutputPath)); // チェックサムファイル内容を生成 const content = this.generateChecksumFileContent(checksumResults); await fs.writeFile(finalOutputPath, content, 'utf-8'); logger.info(`チェックサムファイル保存完了: ${finalOutputPath}`); return createOperationResult(true, `チェックサムファイルが保存されました: ${finalOutputPath}`, finalOutputPath); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`チェックサムファイル保存エラー`, { error }); return createFailureResult(`チェックサムファイル保存に失敗しました: ${errorMessage}`, error instanceof Error ? error : new Error(errorMessage)); } } /** * チェックサムファイルの読み込み */ async loadChecksumFile(checksumFilePath: string): Promise<OperationResult<ChecksumResult[]>> { try { logger.info(`チェックサムファイル読み込みを開始: ${checksumFilePath}`); if (!await fileExists(checksumFilePath)) { throw new Error(`チェックサムファイルが見つかりません: ${checksumFilePath}`); } if (!await canReadFile(checksumFilePath)) { throw new Error(`チェックサムファイル読み取り権限がありません: ${checksumFilePath}`); } const content = await fs.readFile(checksumFilePath, 'utf-8'); const results = this.parseChecksumFileContent(content); logger.info(`チェックサムファイル読み込み完了: ${results.length}エントリ`); return createOperationResult(true, `チェックサムファイルを正常に読み込みました: ${results.length}エントリ`, results); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`チェックサムファイル読み込みエラー: ${checksumFilePath}`, { error }); return createFailureResult(`チェックサムファイル読み込みに失敗しました: ${errorMessage}`, error instanceof Error ? error : new Error(errorMessage)); } } /** * チェックサムファイルに基づくディレクトリ検証 */ async verifyDirectoryIntegrity( directoryPath: string, checksumFilePath: string ): Promise<OperationResult<IntegrityVerification[]>> { try { logger.info(`ディレクトリ整合性検証を開始: ${directoryPath}`); // チェックサムファイル読み込み const loadResult = await this.loadChecksumFile(checksumFilePath); if (!loadResult.success || !loadResult.data) { throw new Error(`チェックサムファイル読み込みに失敗: ${loadResult.message}`); } const results: IntegrityVerification[] = []; const errors: string[] = []; for (const checksumResult of loadResult.data) { const result = await this.verifyFileIntegrity( checksumResult.filePath, checksumResult.checksum, checksumResult.algorithm ); if (result.data) { results.push(result.data); } else { errors.push(`${checksumResult.filePath}: ${result.message}`); } } const validCount = results.filter(r => r.isValid).length; const invalidCount = results.length - validCount; let message = `ディレクトリ整合性検証完了: ${validCount}成功, ${invalidCount}失敗`; if (errors.length > 0) { message += `. エラー: ${errors.length}件`; } logger.info(`ディレクトリ整合性検証完了: ${results.length}ファイル処理`); return createOperationResult(invalidCount === 0 && errors.length === 0, message, results); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`ディレクトリ整合性検証エラー: ${directoryPath}`, { error }); return createFailureResult(`ディレクトリ整合性検証に失敗しました: ${errorMessage}`, error instanceof Error ? error : new Error(errorMessage)); } } /** * チェックサムファイル内容生成(内部用) */ private generateChecksumFileContent(checksumResults: ChecksumResult[]): string { const header = [ '# Enhanced Filesystem Security - Checksum File', `# Generated: ${new Date().toISOString()}`, `# Algorithm: ${checksumResults[0]?.algorithm || 'mixed'}`, `# Total Files: ${checksumResults.length}`, '#', '# Format: <checksum> <algorithm> <size> <filename>', '' ].join('\n'); const entries = checksumResults.map(result => { return `${result.checksum} ${result.algorithm} ${result.fileSize} ${basename(result.filePath)}`; }).join('\n'); return header + entries; } /** * チェックサムファイル内容パース(内部用) */ private parseChecksumFileContent(content: string): ChecksumResult[] { const lines = content.split('\n'); const results: ChecksumResult[] = []; for (const line of lines) { // コメント行と空行をスキップ if (line.trim().startsWith('#') || line.trim() === '') { continue; } const parts = line.trim().split(/\s+/); if (parts.length >= 4) { const [checksum, algorithm, sizeStr, ...filenameParts] = parts; const filename = filenameParts.join(' '); // 型安全性のためのチェック if (checksum && algorithm && sizeStr && filename) { results.push({ filePath: filename, algorithm: algorithm as any, checksum, fileSize: parseInt(sizeStr, 10), timestamp: new Date() }); } } } return results; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mokemoke0821/claude-mcp-integration'

If you have feedback or need assistance with the MCP directory API, please join our Discord server